Introduction

The Eclipse Jetty Contribution Guide targets developers and writers who want to make contributions to the Jetty project by contributing code, writing documentation, or engaging in the larger community.

Mailing Lists

One of the easiest ways to get involved is via our mailing lists:

  • Jetty Users (jetty-users, archives) is for discussion and questions that are of broad interest to the community of Jetty users.

  • Jetty Developers (jetty-dev, archives) is more narrowly focused on technical topics and discussion regarding Jetty internals.

  • Jetty Announcements (jetty-announce, archives) is for announcements about new releases and other updates from the project’s maintainers.

Stack Overflow

Another great resource, both for Jetty novices who need help and Jetty experts who want to contribute, is StackOverflow. In particular, the jetty and embedded-jetty tags see regular traffic.

Filing Issues

You can flag potential bugs or suggest new Jetty features on our issue tracker.

Before filing a new issue, check the tracker to see if it’s already been filed by someone else. If you do file an issue, make sure to label it appropriately, as this will help the development team (and other users) find it more easily.

Help Wanted

If you want to contribute to Jetty but don’t have a specific task or goal in mind, consider looking through our "Help Wanted" issue backlog. These tasks range from the simple to the complex, but they’re all ones we’ve identified as being particularly well-suited for new contributors to tackle.

Commercial Support

Webtide is the company behind Jetty that provides services and support for the Jetty Project.

The Eclipse Contributor Agreement

Since Jetty is a member of the Eclipse Foundation, all contributors must first sign the Eclipse Contributor Agreement (ECA) before their code changes can be merged into source. The Eclipse Foundation maintains an ECA FAQ with more information about the ECA’s provisions.

Before you set up your local development environment, we recommend creating an account at eclipse.org and submitting your signed ECA. Follow the instructions on the Eclipse wiki for details on how to create your account and sign the ECA.

Make sure your emails match

The email address you use to sign the ECA must be the same as the email you use to sign your git commits.

Jetty’s build process has a git hook that verifies each incoming pull request is signed with an email address with an active ECA. If the git hook cannot verify your email, the Jetty committers cannot do anything to accept your commit.

Getting the source code

Jetty’s source is maintained on GitHub at https://github.com/eclipse/jetty.project, where it is managed by the Eclipse Foundation.

You can clone a copy of the Jetty repo onto your local machine by running:

git clone https://github.com/eclipse/jetty.project.git

Related repositories

In addition to the Jetty code repository, we maintain a number of related repositories:

Non-Eclipse Jetty Repositories

https://github.com/jetty-project

Build Toolchain

https://github.com/eclipse/jetty.toolchain

Version branches

If you plan to work on a specific issue within Jetty, make sure to target the correct branch for your pull request.

Table 1. Active Jetty branches

jetty-12.0.x

Development (default branch)

Servlet 6.0

Java 17+

jetty-11.0.x

Maintenance

Servlet 5.0

Java 11+

jetty-10.0.x

Maintenance

Servlet 4.0

Java 11+

jetty-9.4.x

End of Community Support

Servlet 3.1

Java 8+

Maintenance branches are periodically merged into active development branches.

Older branches are only updated if they get specifically targeted by a pull request. Also, changes to older branches aren’t regularly merged forward — although an individual change may be cherry-picked forward, depending on the nature of the fix.

Building Jetty

Jetty’s uses Apache Maven for builds. To successfully build the project, you will also need a recent version of the Java Development Kit (JDK).

Maven and JDK requirements

Here are the minimum Maven and JDK version build requirements for each actively maintained branch.

Table 2. Build versioning requirements by branch
Branch Maven Version Minimum JDK Recommended JDK

jetty-12.0.x

Maven 3.9.2+

OpenJDK 17+

OpenJDK 19

jetty-11.0.x

Maven 3.8.6+

OpenJDK 11+

OpenJDK 17

jetty-10.0.x

Maven 3.8.6+

OpenJDK 11+

OpenJDK 17

To build the Jetty documentation, OpenJDK 19+ is required due to the use of the virtual thread APIs.

Running a fast build

To get started with Jetty as quickly as possible, navigate to your local copy of the Jetty repo and run:

mvn -Pfast clean install

The -Pfast flag tells Maven to bypass running tests and other checks.

Running a full build

To build Jetty and automatically run all tests, run:

mvn clean install

The full build takes substantial time and memory, as it runs hundreds of test cases — many of which spin up embedded instances of Jetty itself.

The build also runs stress tests that may require you (depending on your hardware or operating system) to set you file descriptor limit to a value greater than 2048. You can view or set your file descriptor limit by running:

$ ulimit -n [new_value]
Flagging flaky tests

Not all test cases are as timing independent as they should be, which can result in intermittent test failures. You can help us track these flaky tests by opening an issue when you come across one.

Maven Build Cache

Per default, the build is using the Maven Build Cache extension this means you will use your local build cache, To disable it you can use the property

$ mvn clean install -Dmaven.build.cache.enabled=false

Executing tests in parallel

Jetty uses Junit5’s parallel execution to run test cases in parallel. This behavior is configurable via flags passed to Maven, like so:

mvn install -Djunit.jupiter.execution.parallel.enabled=false

Here are the available configuration flags:

-Djunit.jupiter.execution.parallel.enabled=[BOOLEAN]

Disables parallel execution of tests.

-Djunit.jupiter.execution.parallel.config.fixed.parallelism=[NUMBER]

Configures the number of tests to be executed in parallel.

Certain tests cannot be run in parallel because they access or modify static fields, and are tagged in the codebase with this annotation:

@Isolated("Access static field of Configurations")

Maven will run these tests in isolation even when parallel execution is explicitly enabled.

Optional build tools

  • Graphviz: used by Asciidoctor in the jetty-documentation module to produce various PlantUML graphs.

  • Docker: used to run some integration tests for testing third party integrations.

Build artifacts

Once the build is complete, you can find the built Jetty Maven artifacts in your Maven local repository, along with the following locations of note:

Branch(es) Location Description

all

jetty-home/target/jetty-home-<ver>.tar.gz

The Jetty Home distribution

jetty-12.0.x

jetty-ee10/jetty-ee10-runner/target/jetty-ee10-runner-<ver>.jar

The Jetty Runner distribution for EE10/Servlet 6 (jakarta.servlet) webapps

jetty-12.0.x

jetty-ee9/jetty-ee9-runner/target/jetty-ee9-runner-<ver>.jar

The Jetty Runner distribution for EE9/Servlet 5 (jakarta.servlet) webapps

jetty-12.0.x

jetty-ee8/jetty-ee8-runner/target/jetty-ee8-runner-<ver>.jar

The Jetty Runner distribution for EE8/Servlet 4 (javax.servlet) webapps

jetty-11.0.x

jetty-runner/target/jetty-runner-<ver>.jar

The Jetty Runner distribution for EE9/Servlet 5 (jakarta.servlet) webapps

jetty-10.0.x

jetty-runner/target/jetty-runner-<ver>.jar

The Jetty Runner distribution for EE8/Servlet 4 (javax.servlet) webapps

Code Standards

This section outlines the various coding conventions and standards we use throughout the Jetty codebase.

Configuring your IDE

IntelliJ IDE

An IntelliJ code style XML file is available in the source repo at /build-resources/jetty-codestyle-intellij.xml Follow IntelliJ’s documentation to import these settings into your IDE.

Eclipse IDE

An Eclipse code style XML file is available in the source repo at /build-resources/jetty-codestyle-eclipse-ide.xml.

Java conventions

The following code sample shows some basic Java styles and conventions used throughout the Jetty codebase:

import some.exact.ClassName;      // GOOD
import some.wildcard.package.*;   // BAD!

package org.always.have.a.package;

/**
 * All classes should have a javadoc
 */
class MyClassName
{
    // Use 4 spaces to indent.
    // The code must format OK with default tab size of 8.

    private static final int ALL_CAPS_FOR_PUBLIC_CONSTANTS = 1;

    // Prefix fields with one underscore (_). This
    // convention is not mandatory, but the chosen style
    // should be used consistently within a single class.
    private Object _privateField;

    // Use getters and setters rather than public fields.
    // Braces always on new line.
    public void setPrivateField(Object privateField)
    {
        _privateField = privateField;
    }

    public Object getPrivateField()
    {
        return _privateField;
    }

    public void doSomething() throws SomeException
    {
        Object local_variable = _privateField;
        // Braces always on new line.
        if (local_variable == null)
        {
             // do Something
        }
    }
}

Logging conventions

When deciding when and what to log, bear in mind a few things:

  • Never use LOG.debug() without a preceding if (LOG.isDebugEnabled()).

  • Avoid polluting the log with very long stack traces.

  • Don’t routinely produce logging events in response to data sent by a user.

  • Only call one LOG method for a given event, to avoid generating confusingly interleaved log messages.

  • Never call LOG.warn() right before throwing an exception, as this will likely result in double logging the exception.

  • Avoid calling LOG.debug() right before throwing an exception, as this will make debug logs verbose while adding little information.

  • When interacting with a request or other client-provided data that result in an exception, use DEBUG-level logging:

    catch (Throwable t)
    {
        if (LOG.isDebugEnabled())
            LOG.debug("Something happened {} {} {}",x, y, z, t);
    }
  • When calling into application code that throws an exception, use INFO-level logging, and gate the log with LOG.isDebugEnabled() to reduce the size of logging stack traces:

    catch (Throwable t)
    {
        if (LOG.isDebugEnabled())
            LOG.info("Something happened {} {} {}", x, y, z, t);
        else
            LOG.info("Something happened {} {} {} {}", x, y, z, t.toString());
    }
  • When exceptions happen in Jetty code, and if the exception is (1) not entirely unexpected, (2) can happen relatively frequently, or (3) can potentially have a very long stack trace, you can use LOG.isDebugEnabled() to cut down on the size of the logging of the stacktrace:

    catch (Throwable t)
    {
        if (LOG.isDebugEnabled())
            LOG.warn("Something happened {} {} {}", x, y, z, t);
        else
            LOG.warn("Something happened {} {} {} {}", x, y, z, t.toString());
    }

By default, Jetty’s logger outputs a full stacktrace whether you call it like LOG.warn("Something happened", t) or LOG.warn("Something happened {}", t).

If you only want the log message but not the stack trace, you need to do call .toString() on the caught exception, e.g., LOG.warn("Something happened {}", t.toString()).

Writing Documentation

Another great way to contribute to Jetty is to help us write and maintain our documentation.

Documentation guides

Jetty’s documentation is grouped into three guides, each written for a different target audience.

Operations Guide

Targets sysops, devops, and developers who want to run Jetty as a standalone web server.

Programming Guide

Targets developers who want to use the Jetty libraries in their applications.

Contribution Guide

Targets developers and writers who want to make contributions to the Jetty project.

The documentation toolchain

Jetty follows a "docs as code" philosophy, meaning we use the same tools to write and build our code and docs. As such, the docs are maintained directly within the Jetty codebase at documentation/jetty-documentation/src/main/asciidoc/.

AsciiDoc

Our docs are written in AsciiDoc, a markup language for writing technical content. AsciiDoc supports many advanced features, such as robust linking across different documentation sets, while remaining human-readable.

Although Jetty takes advantage of many of these features, you don’t need to be an AsciiDoc expert to contribute to our documentation. If you are interested in learning the ins and outs of AsciiDoc, the official language documentation is a good place to start.

Maven and Asciidoctor

In addition to using Maven to build the Jetty codebase, we use it to build our docs. During a build, Maven converts AsciiDoc-formatted docs into the HTML pages that you are reading right now.

Asciidoctor is the tool that actually performs this compilation step. Maven integrates with Asciidoctor via the asciidoctor-maven-plugin.

Building the docs

Since Jetty’s docs are maintained in git alongside the rest of the Jetty codebase, you’ll need to check out a local copy of the code to contribute to the docs.

The docs are maintained as a separate module within Jetty, which means you can build the docs separately from the rest of the project. To do so, run mvn clean install from the documentation/jetty-documentation subdirectory.

$ cd jetty.project/documentation
$ mvn install
<...snip...>
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 9.272 s
[INFO] Finished at: 2018-04-09T13:06:10-05:00
[INFO] Final Memory: 74M/247M
[INFO] ------------------------------------------------------------------------

You’ll see a lot of files getting downloaded during the build process. This is Maven setting up the execution environment, which it uses to generate the docs.

When the build completes, you can view the generated docs in your preferred web browser by opening file:///path/to/jetty.project/documentation/jetty-documentation/target/html/index.html on your local filesystem.

Documentation project structure

The documentation root is documentation/jetty-documentation/. Within this root directory are some files and subdirectories of note:

src/main/asciidoc

The primary root for all documentation content.

src/main/asciidoc/config.adoc

This file contains metadata and global variables shared across all the documentation guides. This configuration is used by Asciidoctor to correctly render the final docs.

src/main/asciidoc/*-guide

Secondary root directories for each individual documentation guide.

src/main/asciidoc/*-guide/index.adoc

Asciidoctor’s "point of entry" for each guide. Content is pulled into the guide via the include:: directives in these index files. Also, guide-specific metadata and variables that wouldn’t belong in the root config.adoc can also be defined here.

target/<format>

The final build destination for any docs generated by Maven. By default, docs are generated into target/html, but other formats (e.g., pdf and epub) are available. This directory is not checked into git.

Style guide

The following conventions are not set in stone, but you are encouraged to follow them where possible. Stylistically consistency helps keep the docs easy to both understand and maintain.

Ventilated prose

In markup, each sentence should be on its own line with a hard return at the end of the line. This practice is known variously as ventilated prose or semantic linefeeds.

This practice makes for more readable file diffs, and also makes it easier to comment out individual lines or to move sentences around.

AsciiDoc treats a single line breaks just like a space, so it will render ventilated prose naturally.

Documenting versions

Documenting multiple versions at once

Jetty 12 features many parallel modules with similar names and functionality, but which target different versions of Jakarta EE. For instance, the ee8-deploy, ee9-deploy, and ee10-deploy modules all behave similarly, except they target Jakarta EE8, EE9, and EE10, respectively.

Whenever possible, try to consolidate these types of parallel references. For instance, you can quickly refer to all three of the aforementioned modules as a group by writing ee{8,9,10}-deploy or eeN-deploy.

Another approach is to write your docs targeting one specific module, and tell the reader what substitution(s) they would need to make to target a different module.

When targeting a specific version in your docs for demonstration purposes, you should prefer to use the most recent version number. For the example above, this would mean targeting ee10-deploy.

Consolidating parallel references saves readers from having to sift through repetitive material, and helps us avoid maintaining multiple versions of nearly identical docs.

Dealing with multiple versions in code examples

Instead of referencing multiple versions in your code and command-line examples, it’s generally better to target one specific version, typically the latest (currently ee10):

$ java -jar $JETTY_HOME/start.jar --add-modules=ee10-deploy

This will work when copy-pasted into the command line.

You may want to remind the reader to change the 10 in the command to their preferred target version — although doing so isn’t strictly necessary for a simple example like above.

License blocks

Each .adoc file should contain the license block that exists in the index.adoc file. For reference, here is a standard license header:

//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//

AsciiDoc conventions

Custom IDs

We rely heavily on custom IDs for generating stable documentation URLs and linking within docs.

At minimum, every chapter and top-level section should have its own custom ID; however, best practice is to give each subsection its own custom ID, too.

Custom IDs share a single global namespace, which means they must be unique across all documentation guides. To help deal with this constraint, we used different ID prefixes in each guide:

  • Operations Guide: og-

  • Programming Guide: pg-

  • Contribution Guide: cg-

Images

Images should live in the images/ directory of the guide they appear in. Use the image:: directive to include an image, like so:

image::small_powered_by.gif[image,width=145]
image

Admonitions

Admonitions (or "callout blocks") are useful for flagging information that doesn’t belong in the natural flow of text. Asciidoc supports five levels of admonition:

  • [NOTE]

  • [IMPORTANT]

  • [TIP]

  • [CAUTION]

  • [WARNING]

Each admonition’s visual appearance and typical usage situation are as follows:

A note about the previous case to be aware of.

Important notes are marked with an icon.

Tips that make your life easier.

Places where you have to be careful what you are doing.

Where extreme care has to be taken. Data corruption or other nasty things may occur if these warnings are ignored.

Submitting Patches

We wholeheartedly welcome contributions to Jetty. While not every contribution will be accepted, our commitment is to work with interested parties on the things they care about.

Configuring git

The email in your git commits must match the email you used to sign the Eclipse Contributor Agreement. As such, you’ll likely want to configure user.email in git accordingly. See this guide on GitHub for details on how to do so.

Writing commit messages

If your pull request addresses a particular issue in our repository, then the commit message should reference the issue. Specifically, the message should follow the form Issue #<NNN> <description of the commit>:

$ git commit -s -m "Issue #123 resolving the issue by adding widget"

Using this format will ensure that the commit will be included in VERSIONS.txt upon new releases of Jetty.

Signing the commit

You should sign off on every commit in your pull request using git’s signoff feature (git commit -s).

Time frames

We do our best to process contributions in a timely fashion. Please note that we can only handle pull requests with actively engaged parties. We reserve the right to abandon pull requests whose authors do not respond in a timely fashion.

We will generally adhere to the following time frames for contributions:

Invalid Pull Requests - 1 week

These pull requests do not follow the contribution requirements for some reason — e.g., a missing contributor agreement or mismatched email signature. We will try and follow up with the pull request author to resolve the issue. If we do not hear from the contributor after a week we will close the pull request.

Valid Pull Requests - 2 weeks

If the pull request can be immediately merged, we will do so. Otherwise, we will follow up with the author in a comment to discuss what additional actions must be taken before the change can be landed. If the original contributor does not respond within two weeks, we may close the commit, or make some variation of the commit ourselves.

Security

There are a number of ways to report security issues to the Jetty project.

  • If the issue is directly related to Jetty itself then you are encouraged to report to the Jetty developers directly at security@webtide.com. Webtide employs the active committers of the Jetty project, so this is the preferred reporting method.

We prefer you report any security issues directly to the Jetty developers via email rather than via GitHub Issues, as GitHub does not support private issues.

  • If the issue is related to Eclipse or its Jetty integration then we encourage you to reach out to security@eclipse.org.

  • If the issue is related to some third party integration, we are happy to work with you to identify the proper reporting entity and work with them to properly address the issue. In this case, you are welcome to contact either of the above outreach addresses.

We are generally flexible in how we work with reporters of security issues from an attribution perspective, but reserve the right to act in the interests of the Jetty project in all circumstances.