Understanding Jakarta EE 9

Overview

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 javax.ws.rs:javax.ws.rs-api:2.1.1) and javax java package name (for instance javax.ws.rs.core).

The second release is known as Jakarta EE 8 release. The APIs in Jakarta EE 8 use jakarta maven coordinates (for instance jakarta.ws.rs:jakarta.ws.rs-api:2.1.6), but the javax java package name (javax.ws.rs.core). 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 jakarta.ws.rs:jakarta.ws.rs-api:3.0.0), but the java package name has been changed to jakarta (jakarta.ws.rs.core).

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

Consequences

  • 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 + com.ibm.jbatch:*:2.0.0
  • jakarta.ejb:jakarta.ejb-api:4.0.0
  • jakarta.enterprise:jakarta.enterprise.cdi-api:3.0.0 + org.jboss.weld.se:*: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
  • jakarta.security.**:*: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
  • jakarta.ws.rs:jakarta.ws.rs-api:3.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
  • jakarta.xml.ws:jakarta.xml.ws-api: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):

    @GET
    @Path("sse")
    @Produces(MediaType.SERVER_SENT_EVENTS)
    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 javax.ws.rs java package, but it moves to jakarta.ws.rs 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!

PreInvocationInterceptor

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().

PostInvocationInterceptor

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")
.register(
new PreInvocationInterceptor() {
   @Override
    public void beforeRequest(ClientRequestContext requestContext) {
        startTime = System.currentTimeMillis();
    }  
})
.register(new PostInvocationInterceptor() {
   @Override
   public void afterRequest(ClientRequestContext requestContext,
                            ClientResponseContext responseContext) {
     logDuration(System.currentTimeMillis() - startTime);
   }
  @Override
   public void onException(ClientRequestContext requestContext,
                           ExceptionContext exceptionContext) {
     logDuration(System.currentTimeMillis() - startTime);
   }
 })
.request().get().readEntity(String.class);

InvocationBuilderListener

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 {
        @Override
        public boolean configure(FeatureContext context) {
            context.register(
                 (InvocationBuilderListener)(l)-&gt;
                     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(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
 at org.apache.http.pool.AbstractConnPool.getPoolEntryBlocking(AbstractConnPool.java:379)
 at org.apache.http.pool.AbstractConnPool.access$200(AbstractConnPool.java:69)
 at org.apache.http.pool.AbstractConnPool$2.get(AbstractConnPool.java:245)
 - locked <0x00000000ed700070> (a org.apache.http.pool.AbstractConnPool$2)
at org.apache.http.pool.AbstractConnPool$2.get(AbstractConnPool.java:193)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.leaseConnection(PoolingHttpClientConnectionManager.java:304
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager$1.get(PoolingHttpClientConnectionManager.java:280)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:190)
 at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
 at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
 at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
 at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
 at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:72)
 at org.glassfish.jersey.apache.connector.ApacheConnector.apply(ApacheConnector.java:478)

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):

@Override
protected void configureClient(ClientConfig config) {
    PoolingHttpClientConnectionManager cm
            = new PoolingHttpClientConnectionManager();
    cm.setMaxTotal(11);
    cm.setDefaultMaxPerRoute(11);
    config.property(
            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:

 client.property(ClientProperties.READ_TIMEOUT, 1_000);

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

java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:137)
at org.apache.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:153)
at org.apache.http.impl.io.SessionInputBufferImpl.readLine(SessionInputBufferImpl.java:280)
at org.apache.http.impl.io.ChunkedInputStream.getChunkSize(ChunkedInputStream.java:261)
at org.apache.http.impl.io.ChunkedInputStream.nextChunk(ChunkedInputStream.java:222)
at org.apache.http.impl.io.ChunkedInputStream.read(ChunkedInputStream.java:183)
at org.apache.http.impl.io.ChunkedInputStream.read(ChunkedInputStream.java:210)
at org.apache.http.impl.io.ChunkedInputStream.close(ChunkedInputStream.java:312)
at org.apache.http.impl.execchain.ResponseEntityProxy.streamClosed(ResponseEntityProxy.java:142)
at org.apache.http.conn.EofSensorInputStream.checkClose(EofSensorInputStream.java:228)
at org.apache.http.conn.EofSensorInputStream.close(EofSensorInputStream.java:172)
at java.io.BufferedInputStream.close(BufferedInputStream.java:483)
at java.io.FilterInputStream.close(FilterInputStream.java:181)
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:

    <servlet>
         <init-param>
            <param-name>NAME</param-name>
            <param-value>VALUE</param-value>
        </init-param>
    </servlet>

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 {
    @Override
    public void configure(FeatureContext context) {
        context.property("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 microprofile-config.properties file needs to be created in the META-INF folder. The required properties are then simply set in the microprofile-config.properties:

NAME=VALUE

Then Jersey Microprofile Config extension is needed to be added:

        <dependency>
            <groupId>org.glassfish.jersey.ext.microprofile</groupId>
            <artifactId>jersey-mp-config</artifactId>
            <version>2.29.1</scope>
        </dependency>

And the Microprofile Config implementation, such as Helidon:

        <dependency>
            <groupId>io.helidon.microprofile.config</groupId>
            <artifactId>helidon-microprofile-config</artifactId>
            <version>1.3.1</version>
        </dependency>

Or SmallRye:

        <dependency>
            <groupId>io.smallrye</groupId>
            <artifactId>smallrye-config</artifactId>
            <version>1.3.6</version>
        </dependency>

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

Jersey 2.29 has been released!

It is a pleasure to announce that Jersey 2.29 has been released. It is rather a large release. While Jersey 2.27 was the last non-Jakarta EE release and Jersey 2.28 was the first release of Jersey under a Jakarta EE umbrella, and both of them stayed compatible with Jersey 2.26 as much as possible (binary compatibility, no new API, only updated dependencies and fixes that did not change the Jersey API or behavior), Jersey 2.29 brings many fixes that stacked up since 2.26 and lot of new features, most notably:

  • JDK 11 support
  • Possibility to pass configuration properties through the environment variables
  • Possibility to pass configuration properties using a Microprofile Config implementation
  • Implementation of Microprofile REST Client specification
  • Extension module for Spring 5
  • Possibility to use HK2 Abstract Binder removed in 2.26 again for backward compatibility
  • Enhanced Jetty connector configuration possibilities

Please let us know how you like it!

We are still working on the documentation, though. We have updated the design of a User Guide to correspond with the Jakarta EE style. Now we need to focus on the content, fix what is obsolete and describe new features, that’s our main goal for the silly season!

Posted in Jersey | Leave a comment

Jersey 2.28 has been released

Jersey 2.28 has been released and is available in maven central! Jersey 2.28, the first Jakarta EE implementation of JAX-RS 2.1 has finally been released. Please let us know how you like it!

After whole Java EE has been contributed to the Eclipse Foundation, every project mainly focused on introducing the project and on bringing it closer to the community. From all the tools made available for the community, I’d like to mention Travis CI. It is a great tool that can be used by the community to verify the functionality of provided pull requests. As always Jersey team is happy for them as well as for any other help from the community.

Another goal of Jakarta EE was to create a new release of every project with new versions of dependencies released in the Jakarta EE. In the case of Jersey, the dependencies were updated as much as possible. Of course, sometimes that’s not desired, such as when testing integration with Servlet 2.5 the dependency on Servlet 4.x is not exactly right.

Functionally, we mainly focused on fixing issues, first with building Jersey that was reported by the community, and later some reported differences between Jersey and JAX-RS Specification. This is common for every Jakarta EE project this release: it was required not to provide any changes in API and functionality to ensure the compatibility between last Java EE and initial Jakarta EE releases.

Jersey master contains quite a list of changes, fixes, and improvements to be available in next Jersey release. Currently, there are a few legal details left that need to be resolved so that Jakarta EE projects are allowed to release a version that has API changed, that brings new features, and/or modifies some behavior. Once those legal matters are resolved, a next Jersey release will be created!

Posted in Jersey | 1 Comment

Eclipse Glassfish 5.1.0.RC2 has been released!

That’s right, Eclipse Glassfish 5.1.0.RC2, the Jakarta EE implementation, has been published in maven central. Eclipse Glassfish 5.1.0 release is terribly close.

Latest Glassfish in maven central, Eclipse Glassfish 5.1.0.RC1, publicly available couple of months, is mostly identical to Oracle Glassfish 5.0.1, the latest Java EE reference implementation. It contains many Java EE projects and dependencies, and it has been released mainly for the Eclipse community to introduce Jakarta EE, its functionality, and to demonstrate the commitment of all people working on Jakarta EE.

Eclipse Glassfish 5.1.0.RC2 is very close to the final version, all the Java EE compatibility tests passed there, while it depends on Jakarta EE APIs and implementation rather than Java EE ones.

Comparing Java EE and Jakarta EE, functionally, there is only a minimal difference. That was the goal, to transfer the Java EE to Jakarta EE without changes in the API, so that the community can smoothly deploy the projects from a Java EE application server to the Jakarta EE application server. Only major bug fixes in the functionality were allowed.

Jakarta EE was focused on bringing the projects close to the community. Everyone with enough enthusiasm can start contributing to a project and become a committer. Most of the projects do use Travis CI and the projects contain Travis scripts so that anyone who wants to contribute can run the tests in his own GitHub fork on Travis CI (after registering there). For the projects, committers have access to Eclipse Jenkins infrastructure, where any build and test jobs can be set up. Unlike with Java EE, the compatibility tests are available, with a description of how to use them. There is a Jakarta EE wikipedia, and each project has its own mailing list.

Apart from these new things, the license of projects has been changed. The code is available under EPL 2.0 license, whereas examples are available under EDL 1.0 license.

The main positive thing, though, is that it is the interest of the community that decides about the future of the Jakarta EE projects.

Posted in Jakarta EE | Leave a comment