Jersey 2.35, and Jersey 3.0.3

Jersey 2.35 and corresponding Jersey 3.0.3 have been released recently. There is a number of new features.

We support JDK 17, JDK 16, JDK 15, JDK 14, JDK 13, JDK 12, JDK 11, and JDK 8. It means, Jersey is tested there, passes tests, and is perfectly functional. Except… It does not mean we support JDK 16 records. It does not mean we use JPMS and define the module-infos. It does not mean HTTP Patch requests work with the default HttpUrlConnector on JDK 16. But we are working on these features, too.

We support the Graal VM native image (please read the documentation and try our example). We support Optional<T> in the HTTP request parameters (QueryParam, PathParam,…). We implement MP Rest Client 2.0 (we are also compatible with MP Rest Client 1.4 API).

But mainly, we make progress towards Jakarta REST 3.1, and Jakarta REST 4.0.

Jakarta REST 3.1 brings a requirement that Feature and Dynamic Feature must be possible to define as a JDK service (by adding provider-configuration file) and it is loaded by the implementation. We allow this feature in Jersey 2.35 and 3.0.3, too.

Jakarta REST 3.1 introduces MultiPart API. Jersey supports MultiPart already, using Jersey API. We added support of RFC 5987 filename attributes.

The most important change planned for Jakarta REST 4.0 is the mandatory CDI integration. JAX-RS 2.0 introduced optional CDI integration: In a product that supports CDI, implementations MUST support the use of CDI-style Beans as root resource classes, providers and Application subclasses. Jakarta REST 3.1 deprecates @Context annotation: Note that future versions of this API will stop supporting injection via @Context as part of a tighter integration and alignment with Jakarta CDI.

Jersey 2.34 introduced a new module org.glassfish.jersey.ext.cdi:jersey-cdi-rs-inject, which enables injecting Jakarta REST injectables normally injected by @Context to be injected using @Inject, when using CDI. It is enough just to add the module to a classpath. This is one step towards pure CDI injection.

Jersey 2.35 introduced an experimental module org.glassfish.jersey.incubator:jersey-cdi-inject-weld. This module implements an InjectionManager that is completely CDI-based, with no HK2 involved. Currently, it works just with the jersey core modules, and we have an example that shows the module working (when running with “CdiInjectWeld” profile). This module will definitely be a subject of changes in the future. The current plan is to support CDI lite and CDI lite can be a reason for the complete redesign of the module. CDI lite, as well as CDI 4.0, is a subject for Jakarta EE 11, and the details of the changes are not known, yet.

Soon, Jakarta REST 3.1 release candidate will be released, and the first milestone release of Jersey 3.1.0 will follow. These artifacts are part of Jakarta EE 10 which is finishing and will go through a release review ballot; Jakarta EE 10 will be out during this winter.

Posted in Jersey | Leave a comment

Very Merry Christmas with Jersey 2.33

Jersey 2.33 is out! As usually, right before Christmas we put together as many fixes and new features as possible to deliver new Jersey for you, the Jersey customers.

During the work on Jersey 2.33, we already delivered Jersey 3.0.0, which kept us busy, and there not as many changes as usual for a regular release. Jersey 2.33 contains mainly fixes and we were thinking about a service 2.32.1 release.

There is one significant change in Jersey 2.33, however. We decided to make JAX-B API optional. When there is JAX-B API among dependencies on the classpath, it works as ever. However, if it is not there, Jersey prints a warning, but would not fail. Please make sure you add the JAX-B dependency if you need it, from now on.

We decided on this for multiple reasons. We register requests for this change from microservices guys who try to make the application the smallest possible and they do not use JAX-B or WADL. They also customize their JDK not to contain javax.xml and javax.awt modules and we made them optional. And it is the future of Jakarta RESTful Web Services, too. The next version of the Specification will mandate the JAX-B dependency optional.

For the complete list of changes, check the Jersey 2.33 release details. As always, we are happy to hear your feedback. If any issue is found, contact us on our issue tracker, or just send us an email about how you like Jersey.

Posted in Jersey | Leave a comment

Happy Jakarta EE 9 with Jersey 3.0.0

Jakarta EE 9 and Jersey 3.0.0 are here. The transition to a new jakarta package based APIs took a great amount of work, from the whole Jakarta EE community. It started in the spring of the year 2020, and finally, Jakarta EE 9 is almost there! There are just a few missing bits not yet released to maven central coming very soon!

Jersey 3.0.0 pre-releases and dependencies

Jersey is split into many modules which has a dependency on so many APIs and their respective implementations, JAX-RS, JAX-B, JSON-P, JSON-B, Servlet, JSP, EJB, HK2, CDI, Bean Validation, Inject, Interceptor, … All of these projects did all necessary work to be transitioned to Jakarta EE 9, and it has been possible to get Jersey 3.0.0. released to maven central, eventually.

Jersey 3.0.0 has few milestone releases. Each milestone release adopted a new subset of Jakarta EE 9 APIs, and finally, we were able to pass Jakarta EE 9 RESTful Web Services TCK with Jersey 3.0.0-M6. Since then, we marked the releases as release candidates.

Jersey 3.0.0 final has several dependencies not yet final, some are release candidates, but some are beta (Weld), or even alpha (Hibernate Validator). All the Jakarta EE 9 API dependencies are final, however!

How to try

Feel free to try Jakarta EE 9 and Jersey 3.0.0. It is available either as a part of Glassfish 6.0.0 (RC1 and RC2 are available in maven central, and Glassfish 6.0.0 final is on its way), or standalone in maven central, as usual.

Changes to Jersey 2.x

Jersey 3.0.0 keeps most of the Jersey 2.x features. It is still able to support Jackson 2 (we dropped the obsolete Jackson 1 support), see the examples. We also keep supporting the MicroProfile Config. Jersey 3.0.0 does not support the MicroProfile REST client, however, since it has a strong JAX-RS 2.1 dependency. We also dropped the Helidon Connector module for the time being.

Jersey 3.0.0 uses Jetty in many tests and examples. Compatible Jetty 11 dropped support of JDK 8, hence those examples and tests require JDK 11+ to run.

Contact us

Jakarta EE 9 is backward incompatible with Jakarta EE 8. We tried to keep most features and functionality the way it is in Jersey 2.x to ease a transition of applications to Jakarta EE 9. The API package name is still a huge change and if any issue is found, contact us on our issue tracker, or just send us an email about how you like Jersey.

Posted in Jakarta EE, Jersey | Leave a comment

Understanding Jakarta EE 9


Java Enterprise Edition, or Java EE, is a set of standards defined to be used in an enterprise environment, implemented by a set of Java EE compatible application servers. Java Enterprise Edition or JEE (formerly Java 2 Enterprise Edition, or J2EE) is being developed for more than a decade, starting with the first J2EE 1.2 release in 1999. In 2017-2018, the entire Java EE was contributed to the Eclipse Foundation, and it is known as Jakarta EE now.

There are 3 known releases of Jakarta EE, each with a different variation of maven coordinates and java package name. The first has been announced in January 2019. It was a technical release, almost identical to Java EE 8, and it was marked by a code name EE4J_8 (every Jakarta EE/EE4J project used to have a git branch with this code name). It was a release to prove that the Java EE contributed code is complete. This release was not Jakarta EE release, yet. The APIs used javax maven coordinates (for instance and javax java package name (for instance

The second release is known as Jakarta EE 8 release. The APIs in Jakarta EE 8 use jakarta maven coordinates (for instance, but the javax java package name ( Jakarta EE 8 is (99.9%) backward compatible with Java EE 8.

The third, very soon upcoming release, is known as Jakarta EE 9. The APIs in Jakarta EE 9 use jakarta maven coordinates (for instance, but the java package name has been changed to jakarta (

Jakarta EE 9 hence is NOT BACKWARD COMPATIBLE with Java EE 8!


  • Every API needs to transition the java package from javax to jakarta.
  • Every Specification needs to get updated to reflect the new API changes.
  • Every implementation of a respective Specification needs to be adjusted to handle the new APIs.
  • New versions of application servers need to be released. Many Specifications are involved for instance with the Servlet container and/or CDI and therefore the new implementations won’t work on the old (Java EE-based) application servers, and the old implementations won’t work on the new (Jakarta EE 9-based) application servers.
Jersey 3 needs Jakarta EE 9-based server, such as Glassfish 6, Jetty 11, Tomcat 10!
Jersey 2 needs Java EE 8/Jakarta EE 8-based server, such as Glassfish 5, Jetty 9/10, Tomcat 9!
  • For the java package name change, Jakarta EE 8 API does not work with Jakarta EE 9 implementation and vice versa.
  • In cases, when both the Java EE API would be needed (such as when using JAX-B API with Jackson), and Jakarta EE 9 API would be needed (for other JAX-B usages), mixing Jakarta EE 8 and Jakarta EE 9 API would cause issues with maven (since both use the same maven coordinates). Instead of Jakarta EE 8 jars, the older Java EE 8 jars would better be used.
Do not mix Jakarta EE 8 and Jakarta EE 9 artifacts!

Jakarta EE 9 / EE4_J artifacts

It is not very easy to recognize Jakarta EE9 APIs and compatible implementations. It’s the artifact versions that matter. To name some:

  • jakarta.activation:jakarta.activation-api:2.0.0 + com.sun.activation:jakarta.activation:2.0.0
  • jakarta.annotation:jakarta.annotation-api:2.0.0
  • jakarta.authentication:jakarta.authentication-api:2.0.0
  • jakarta.authorization:jakarta.authorization-api:2.0.0
  • jakarta.batch:jakarta.batch-api:2.0.0 +*:2.0.0
  • jakarta.ejb:jakarta.ejb-api:4.0.0
  • jakarta.enterprise:jakarta.enterprise.cdi-api:3.0.0 +*:4.0.0
  • jakarta.enterprise.concurrent:jakarta.enterprise.concurrent-api:2.0.0
  • jakarta.el:jakarta.el-api:4.0.0
  • jakarta.faces:jakarta.faces-api:3.0.0 + org.glassfish:jakarta.faces:3.0.0
  • jakarta.inject:jakarta.inject-api:2.0.0
  • jakarta.interceptor:jakarta.interceptor-api:2.0.0
  • jakarta.jms.jakarta.jms-api:3.0.0
  • jakarta.json:jakarta.json-api:2.0.0 + org.glassfish:jakarta.json:2.0.0
  • jakarta.json:jakarta.json.bind-api:2.0.0 + org.eclipse:yasson:2.0.0
  • jakarta.jws:jakarta.jws-api:3.0.0
  • jakarta.mvc.jakarta.mvc-api:2.0.0 + org.eclipse.krazo:*:2.0.0
  • jakarta.persistence:jakarta.persistence-api:3.0.0 + org.eclipse.persistence:*:3.0.0
  •**:*:2.0.0 + org.glassfish.soteria:*:2.0.0
  • jakarta.servlet:jakarta.servlet-api:5.0.0
  • jakarta.servlet.jsp:jakarta.servlet.jsp-api:3.0.0
  • jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api:2.0.0
  • jakarta.transaction:jakarta.transaction-api:2.0.0
  • jakarta.validation.jakarta.validation-api:3.0.0 + org.hibernate.validator:hibernate-validator:7.0.0
  • jakarta.websocket:jakarta.websocket-api:2.0.0 + org.glassfish.tyrus:*:2.0.0
  • + org.glassfish.jersey:*:3.0.0
  • jakarta.xml.bind:jakarta.xml.bind-api:3.0.0 + com.sun.xml.bind:*:3.0.0
  • + com.sun.xml.*:*:3.0.0

The list goes on, especially for every Jakarta EE 9 compatible implementation from various vendors.

The artifacts are not available in maven central

The artifacts are not available in maven central, yet. Some of them are, in the milestone version (Jersey 3.0.0-M6), some in Alpha, or Beta (Bean Validation implementation, Weld), some in release candidate versions (EJB API), some in the final version (CDI API) but one day, it will all be there.

The final versions of the APIs/Specifications go through so-called ballots, and once the ballot is approved, it can be released to maven central. Then, when other technologies have all the dependencies gone through the ballots, they can go through the ballots as well. The ballots are processed in waves, and October 2020 is the most active month regarding the ballots to get Jakarta EE 9 released on November 20.

Jakarta EE 9 is finishing to be released on November 20.

The progress on Jakarta EE 9 can be viewed by observing Glassfish 6 weekly builds. While the Jakarta EE 9 bits may not be available in maven central, yet, Glassfish 6 may already integrate them. For Jersey and Tyrus, the milestone versions are available in maven central, since all used dependencies are available in maven central, too. Glassfish contains release candidates, that are not available in maven central, yet, and they will get there once the dependencies are there. We mark them as release candidates since the final version of the Jakarta Restful Web Services API / Jakarta WebSocket API is referenced. As soon as all the TCKs are passing, the release candidate of Glassfish is planned. The Glassfish is not tested on JDK 11, or newer, yet.

The initial Jakarta EE 9 is required just to work on JDK 8.

Jakarta EE 9.1 is planned very soon after the initial release, and it will be compatible with JDK 11 (as well as with JDK 8).

What happened with JAX-RS acronym

Java API for RESTful Web Services (JAX-RS) continues as Jakarta Restful Web Services. To distinguish between Java EE and Jakarta EE, Jakarta Restful Web Services stopped using the JAX-RS acronym. The acronym is no longer used in the Specification document, nor in the API, nor the TCK document. The full Jakarta Restful Web Services name is used there instead. The discussion about a better acronym/abbreviation did not find a final replacement, yet. The most favorable seems to be Jakarta REST, but people keep using the JAX-RS acronym during a discussion.

The full Jakarta Restful Web Services name is prefered over JAX-RS acronym for the time being to distinguish between Java EE and Jakarta EE.
Posted in Jakarta EE, Jersey | Leave a comment

What is new in Jersey 2.32

Recently, Jersey 2.32 has been released. Jersey 2.x is a continuous evolution of Jersey implementing JAX-RS 2.1 Specification. While the successor Jakarta Restful Web Services 3.0 Specification, which is part of the Jakarta EE 9 initiative, will bring a lot of new features that will be implemented in Jersey 3.x (currently in 3.0.0-M6 release – which passes the Jakarta EE 9 Restful Web Services TCK already), and Jersey 3.x will become the main evolution branch, we see many requirements to keep developing Jersey 2.x for several additional years.

Jersey 2.32 (or newer) is the JAX-RS implementation that is going to be used in Helidon 2.0.3, and it also is planned to be part of the Weblogic Application Server 14.1.2.

Jersey 2.32 supports JDK 8, and JDK 11-JDK 15 (since Jersey 2.31). Along with interfaces PreInvocationInterceptorPostInvocationInterceptor, and InvocationBuilderListener, introduced in Jersey 2.30, an additional ClientBuilderListener interface has been added. Unlike the first two, it is not registered on the client, rather it is used as a service (defined in META-INF/services) so that it can be invoked before the Client is created.

Helidon 2 comes with a new reactive HTTP client called WebClient based on Netty HTTP client. Jersey 2.31 came with an alternative connector that uses the Helidon WebClient for HTTP requests using the WebClient by JAX-RS/Jersey client syntax. It has been built using Helidon 2.0.0-RC2 and as with the other connectors. The Helidon API changed, however, between Helidon 2.0.0-RC2 and Helidon 2.0.0 and the connector implementation was contributed to Helidon. Hence Jersey 2.32 comes with HelidonConnectorProvider that simply reuses the connector from Helidon. This way, the connector reflects the most recent changes in the implementation in Helidon (we recommend to use with Helidon 2.0.3, or later, when available, the maven dependency on Helidon connector is therefore provided in Jersey Helidon Connector module).

We made improvements to Netty and Apache connector, too. The Netty connector is configurable using NettyClientProperties, Apache connector accepts HttpEntity type in JAX-RS Entity. The default HttpUrlConnector now supports Expect:100-continue HTTP header using Expect100ContinueFeature.

Registering features now supports priorities on features. Both using @Priority or register(feature, priority) are legitimate options. This allows for the ordering of the execution of the features.

MicroProfile Rest Client implementation is now compatible with MicroProfile Rest Client 1.4.1 Specification. It also allows for using regular expressions in @Path annotation now.

We modified SSE, so now it is possible to do all of the following (in case of JDK8 the last 2 lines are not applicable):

    public void register(@Context SseEventSink eventSink)
    public void register(@Context org.glassfish.jersey.internal.jsr166.Flow.Subscriber<String> eventSink)
    public void register(@Context org.glassfish.jersey.internal.jsr166.Flow.Subscriber<OutboundEvent> eventSink)
    public void register(@Context java.util.concurrent.Flow.Subscriber<String> eventSink)
    public void register(@Context java.util.concurrent.Flow.Subscriber<OutboundEvent> eventSink)

For additional changes and details, it is possible to check release 2.32, and 2.31, respectively.

Posted in Jersey | Leave a comment

Jersey 2.30.1 has been released

It has been a while since we have released Jersey 2.30. On the client-side, we introduced new PreInvocationInterceptorPostInvocationInterceptor, and InvocationBuilderListener interfaces. We made the default Rx client using the AsyncInvoker (unlike the RxInvokerProvider). We worked hard to make the Apache HttpClient Connector working with the new Apache Http Client as fine as the old days. We allowed the MP REST Client to work with any Jersey connector.

On both the client and server-side, we allowed the HeaderDelegateProvider to work again. We improved the integration with CDI. We allow some of the default AWT and/or XML related providers to be disabled. The full change list can be observed here.

Mainly, we created a multi-release jar for our WADL doclet extension, which works with JDK 13. So Jersey 2.30 is the first release that is fully buildable and works on JDK 13. Hurray!

Unfortunately, we made the release with JDK 12, and the 2.30 multi-release core-common jar now contains byte code for JDK 8, and for JDK 12+.

Jersey 2.30.1 mainly fixes the bug for the core-common multi-release jar, which works with JDK11, again (the same as Jersey 2.29.1). Other fixes and improvements were put in. We improved the integration with the Netty client and server. We better handle multiple cookies with the same name. We made a step towards Jersey being used in Glassfish 6. And we successfully made it through the Release Review.

For the next release, we continue to be working on Jersey 2.x, and we started to work on Jersey 3.x. Jersey 2.x continues to be compatible with JAX-RS 2.1.6 API, and we plan to keep it working with JDK 8, JDK 11, JDK 12, JDK 13, and we also plan to support JDK 14 as soon as possible. Jersey 3.x will be compatible with Jakarta RESTful WebServices 3.x.y API, which no longer uses java package, but it moves to package, similarly to all Jakarta EE 9 projects. Jersey 3.0.0 still will work with JDK 8, but it is possible that Jakarta RESTful WebServices API 3.1.0 or later will require JDK 11 features, and at that point, the backward compatibility with JDK 8 can be abandoned by Jersey 3.x.

Posted in Jersey | Leave a comment

New Features in Jersey Client

Jersey 2.30 comes with multiple new features, and this post describes three new interfaces on the client. They are PreInvocationInterceptor, PostInvocationInterceptor, and InvocationBuilderListener.

Suppose a case that the start of the request is to be logged and even measured. This can be done by ClientRequestFilter, which is usually invoked before the request is wired on the network. However, the filter may be called as a last of the filters in the chain. Sure, it can have the highest priority, but the other filters can have the very same priority! Some long-running operations can be performed before the measuring can actually start. Even worse, the filter may even be skipped from the chain by the previous #abortWith!


For this, PreInvocationInterceptor, the code that executes before the ClientRequestFilters are invoked, has been added to the client request chain. Jersey ensures all the interceptors are invoked with each request. The interceptor contains a single #beforeRequest method, which corresponds to ClientRequestFilter:

     * The method invoked before the request starts.
     * @param requestContext the request context shared with
     * ClientRequestFilter.

   void beforeRequest(ClientRequestContext requestContext);

Note that only a single #abortWith is allowed in all PreInvocationInterceptors, otherwise an IllegalStateException is thrown. All the exceptions accumulated in PreInvocationInterceptors are thrown in a single Exception, available through #getSuppressed().


Similarly, ClientResponseFilter seems to be a good place where the total time of the HTTP request can be measured, but similarly to ClientRequestFilter, the response filter may not be invoked at all. For this, PostInvocationInterceptor has been introduced. Jersey runtime ensures that every PostInvocationInterceptor is called. Since an exception can occur during the HTTP request, PostInvocationInterceptor comes with two methods:

     * The method is invoked after a request when no
     * is thrown, or the Throwables are resolved
     * by previous PostInvocationInterceptor.
     * @param requestContext the request context.
     * @param responseContext the response context
     * of the original Response or response context
     * defined by the new resolving Response.

    void afterRequest(ClientRequestContext requestContext,
                      ClientResponseContext responseContext);

     * The method is invoked after a Throwable is caught
     * during the client request chain processing.
     * @param requestContext the request context.
     * @param exceptionContext the context available to handle the
     * caught Throwables.

    void onException(ClientRequestContext requestContext,
                     ExceptionContext exceptionContext);

The #afterRequest method is executed when no exception has been thrown during the HTTP request, #onException method is executed if the exception has been thrown during the request. It is possible to set a response in #onException, and the consecutive PostInvocationInterceptor will execute its #afterRequest method.

The measuring example can looks as follows, then:

String response = ClientBuilder.newClient().target("path")
new PreInvocationInterceptor() {
    public void beforeRequest(ClientRequestContext requestContext) {
        startTime = System.currentTimeMillis();
.register(new PostInvocationInterceptor() {
   public void afterRequest(ClientRequestContext requestContext,
                            ClientResponseContext responseContext) {
     logDuration(System.currentTimeMillis() - startTime);
   public void onException(ClientRequestContext requestContext,
                           ExceptionContext exceptionContext) {
     logDuration(System.currentTimeMillis() - startTime);


InvocationBuilderListener is an interface that is inspired by Microprofile REST Client RestClientBuilderListener and it contains a single method:

     * Whenever an Invocation.Builder is created, (i.e. when
     * WebTarget#request() is called, this method would be invoked.
     * @param context the updated InvocationBuilderContext.

    void onNewBuilder(InvocationBuilderContext context);

InvocationBuilderContext a subset of methods of the Invocation.Builder. It can be used to call the default values of the Invocation.Builder. Since it is invoked at the time Invocation.Builder is instantiated, any consequent calls of the Invocation.Builder‘s methods will replace the defaults set by the InvocationBuilderListener.

For instance, if all the HTTP requests should contain a custom HTTP header, there can be created a feature that would be registered on the client:

  public static class MyFeature implements Feature {
        public boolean configure(FeatureContext context) {
                     l.getHeaders().add("MY_HEADER", "MY_VALUE"));
            return true;

And More!

Jersey 2.30 comes with more new features on the client, most notably a possible hanging when using the Apache Client Connector has been fixed and the Microprofile Rest Client implementation has been allowed to use connectors.

Posted in Jersey | Leave a comment

Jersey Apache Connector Hangs …?

Jersey comes with various connectors to third-party HTTP clients. The way the connector is used is simple, put the connector and the third-party client to the classpath, and tell the client to use it. For Apache Connector, use:

ClientConfig clientConfig = new ClientConfig();
clientConfig.connectorProvider(new ApacheConnectorProvider());
Client client = ClientBuilder.newClient(clientConfig);

Switching from the default HttpUrlConnectorProvider to ApacheConnectorProvider may not be as smooth as expected, and the connection can hang. Surprisingly, even switching the provider in Jersey tests and examples in Jersey workspace. For instance, adding Apache connector to org.glassfish.jersey.tests.e2e.sse.BroadcasterCloseTest can result in a thread lock similar to:

java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for  <0x00000000ee799320> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(
 at org.apache.http.pool.AbstractConnPool.getPoolEntryBlocking(
 at org.apache.http.pool.AbstractConnPool.access$200(
 at org.apache.http.pool.AbstractConnPool$2.get(
 - locked <0x00000000ed700070> (a org.apache.http.pool.AbstractConnPool$2)
at org.apache.http.pool.AbstractConnPool$2.get(
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.leaseConnection(
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager$1.get(
at org.apache.http.impl.execchain.MainClientExec.execute(
 at org.apache.http.impl.execchain.ProtocolExec.execute(
 at org.apache.http.impl.execchain.RetryExec.execute(
 at org.apache.http.impl.execchain.RedirectExec.execute(
 at org.apache.http.impl.client.InternalHttpClient.doExecute(
 at org.apache.http.impl.client.CloseableHttpClient.execute(
 at org.glassfish.jersey.apache.connector.ApacheConnector.apply(

The problem is the test code, the response is never closed. The Apache Connection pool does not have enough threads to execute all the requests since the response is not closed and thus the connection is not closed. The solution can be simple, call response.close() after the assertion in the for-each loop as well as for 2 more responses. Note that the third request is closed automatically when response.get(String.class) is called.

The general rule is to close anything that can be closed if not needed (Client, Response, SseEventSink, SseEventSource). Response.close() does not close the buffered entity, it can be read multiple times. If the entity is an InputStream, do not forget to close it, too.

Sometimes, the response cannot be closed, yet, and multiple connections need to be open. This time, the Apache Connector needs to be provided with more threads. For BroadcasterCloseTest, eleven is enough (in case the responses are not closed):

protected void configureClient(ClientConfig config) {
    PoolingHttpClientConnectionManager cm
            = new PoolingHttpClientConnectionManager();
            ApacheClientProperties.CONNECTION_MANAGER , cm);
    config.connectorProvider(new ApacheConnectorProvider());

There is a case where the Jersey Apache Connector hangs even if everything is done properly. Apache HttpClient 4.5.1 comes with a change that may cause Jersey Apache Connector in the case where chunked streams are used. An example when this happens is StreamingTest#clientCloseTest. Jersey 2.28 depended on Apache HttpClient 4.5, and the Apache Connector did not hang with it. Jersey 2.29 came with newer Apache Connector and for the StreamingTest#clientCloseTest to pass, a timeout 1000ms has been added:, 1_000);

Without the timeout, the connector hangs, and the stack trace is as follows:

java.lang.Thread.State: RUNNABLE
at Method)
at org.apache.http.impl.execchain.ResponseEntityProxy.streamClosed(
at org.apache.http.conn.EofSensorInputStream.checkClose(
at org.apache.http.conn.EofSensorInputStream.close(
at org.glassfish.jersey.apache.connector.ApacheConnector...

Jersey 2.30 contains a workaround for the changed Apache Http Client 4.5.1+ and the timeout is not needed to be added in the client code anymore.

Posted in Jersey | 5 Comments

Configuring Jersey Application

It is a common issue, I am asked about every now and then, how to pass the user data to a user application? The user needs to change the code behavior depending on the configuration data. This is where the @Context Configuration comes handy.

In the following text, I try to describe the possible methods to pass the user’s property to the Configuration object so that it is available when it is injected.

Hardcode in the Application/ResourceContext

This is the simplest way, just set the property just like:

new ResourceConfig().property("NAME","VALUE")

Using web.xml Initial Parameters

For classic war bundled applications, the properties can be defined in the web.xml:


Using the AutoDiscoverable

Jersey comes with AutoDiscoverable SPI, which allows for being detected by a JDK’s ServiceLoader when anywhere on a classpath. Such AutoDiscoverable is then used as if it were a part of the application. The advantage is that the application itself does not need to be rebuilt, only the AutoDiscoverable with the properties.

The org.glassfish.jersey.internal.spi.AutoDiscoverable service needs to be added to META-INF/services, and it needs to point to the AutoDiscoverable implementation:

public class MyAutoDiscoverable implements AutoDiscoverable {
    public void configure(FeatureContext context) {"NAME", "VALUE");

Using the System Properties

Quite often, the administrators come and ask to configure Jersey application, mainly to use any of the CommonProperties property, but they do not want to recompile their Jersey application, nor the AutoDiscoverable. Since Jersey 2.29 it is possible to turn on the ability to convert the System properties into Configuration properties. That can be done by using the System property, too:

java -Djersey.config.allowSystemPropertiesProvider=true -DNAME=VALUE

Note that with the security manager turned on, write access permission is required to execute System.getProperties(). With insufficient permissions, the warning message is logged (with Level.FINER) and only CommonProperties, ClientProperties, and ServerProperties properties are used, as the property names are known and System.getProperty(name) method can be used, which does not require the write access permission.

Using Microprofile Config

Microprofile platform became very popular lately and Microprofile Config Specification is a recommended way in the Jakarta EE world to configure the specifications under the Jakarta EE umbrella.

Jersey 2.29 comes with support for Microprofile Config implementation such as Helidon or SmallRye. To configure the Jersey application, the file needs to be created in the META-INF folder. The required properties are then simply set in the


Then Jersey Microprofile Config extension is needed to be added:


And the Microprofile Config implementation, such as Helidon:


Or SmallRye:


or any other suitable Microprofile Config implementation.

Other Methods

There are other methods that are variants to the described methods, or they are less straightforward and significantly more complicated. However, if you have any other favorite method that was not discussed, I’d love to hear about it in the comments.

Posted in Jersey | Leave a comment

Jersey 2.29.1 has been released!

What a busy summer! Jersey 2.29 has been released in June and Jakarta EE 8 release was the next goal to be achieved before Oracle Code One.

It has been a lot of work. Jakarta EE 8 contains almost 30 different APIs, one-third of which Jersey depends on. Fujitsu, IBM, Oracle, Payara, RedHat, Tomitribe, Eclipse Foundation, the individual contributors, everyone worked hard to follow the new certification process to get the Certification of Compatibility of the new APIs released as part of Jakarta EE together with the respective implementations.

As of today, three application servers were announced to be certified Jakarta EE 8 Application Servers, Eclipse Glassfish 5.1, IBM OpenLiberty and RedHat WildFly announced they are fully certified as a compatible implementation of the Jakarta EE 8 profiles.

Jersey team provided a great deal of help with the certification, building some of the APIs, creating the TCK jobs and run some of the TCKs, …, and yet the team was able to deliver a new version of Jersey!

Jersey 2.29.1 is mainly a maintenance release, with a couple of fixes, and three main new features. It depends on the new Jakarta EE 8 APIs (mainly JAX-RS 2.1.6), it provides ApacheHttpClientBuilderConfigurator to improve the ability to configure Apache Http Client, and it provides a Microprofile Rest Client 1.3.3 implementation. The full list of features is available here.

Please give it a try and let us know how you like it.

Posted in Jakarta EE, Jersey | Leave a comment