Transition from Java EE to Jakarta EE? EE Conclusion What Happened and What You Need to Know
Total Page:16
File Type:pdf, Size:1020Kb
Search Java Magazine Menu Topics Issues Downloads Subscribe Transition from Java EE to Jakarta JAVA EE EE What Has Been Going on with Java Transition from Java EE to Jakarta EE? EE Conclusion What happened and what you need to know by Arjan Tijms February 27, 2020 Java EE is undoubtedly one of the most recognizable frameworks for server-side Java. It essentially kick-started the industry for using Java on the server, and it goes all the way back to the very beginnings of Java in 1996 with Kiva Enterprise Server (GlassFish) and the Tengah application server (the Oracle WebLogic Server ancestor). Note that here, the word Tengah refers to an administrative region in the center of the island of Java in Indonesia. Java EE, or J2EE (Java 2 Enterprise Edition) as it was known before, is perhaps best known for its Java Servlet specification and for servers implementing that, such as Tomcat and Jetty. These are often called servlet containers. Although there are alternatives, many server applications and third-party frameworks are based on the Java Servlet specification. Besides this specification, Java EE in later years became known for its specifications for persistence (Java Persistence API [JPA], mostly via Hibernate), REST (JAX-RS), WebSocket, and a slew of smaller specifications such as for transactions (Java Transaction API [JTA], mostly used under the covers by JPA), for validation (Bean Validation), and for JSON (JSON-P and JSON-B). In practice, some applications that might not seem to be classified as Java EE applications might use a variety of Java EE APIs. Full implementations of Java EE, traditionally used in application servers, have enjoyed considerable success as well: JBoss/WildFly, GlassFish/Payara, and, more recently, Open Liberty (the modern successor of WebSphere) are all well known. Then there’s a group of products that are neither application servers nor servlet containers, but do support a variety of Java EE APIs out of the box. These include Quarkus (Contexts and Dependency Injection [CDI], JAX-RS, JPA), Helidon (CDI, JAX-RS, JPA, JTA), KumuluzEE (CDI, JAX- RS, JPA, Servlet, JavaServer Faces [JSF], WebSocket, Bean Validation, JSON-P), and Piranha (CDI, JAX-RS, Java EE Security, Expression Language [EL]). Finally there’s the Java EE offspring platform called MicroProfile, which directly depends on Java EE APIs such as CDI, JAX-RS, and JSON. All together this makes the Java EE APIs quite relevant for a large group of users. What Has Been Going on with Java EE? The last release of Java EE proper was Java EE 8 in August 2017. This was a scope-reduced release, although it did contain important key functionality, such as Java EE Security. Oracle decided later that year to transfer Java EE fully to an open source foundation. In coordination with Java EE partners Red Hat and IBM, it was decided to transfer Java EE along with the full reference implementation and the Technology Compatibility Kit (TCK) to the Eclipse Foundation. Due to the enormous amount of work involved with this transfer, the process was split into three stages. Stage 1: Transfer API and implementation code and release a verified build. The first stage involved creating a new top-level project at Eclipse called Eclipse Enterprise for Java (EE4J). The EE4J project and its associated GitHub organization, eclipse-ee4jz, are home to both the specification and implementation projects. EE4J should not be confused with the new brand name for Java EE, Jakarta EE, which was selected several months later by the community. Before the actual transfer of all the existing source code from the Oracle repository at github.com/javaee could be done, all the code had to be cleared legally, which among other things meant potentially controversial portions had to be removed. Weighing in at many million lines of code, this was clearly no small task. Applying this legal clearing to all the historical code as well would have been simply undoable. Therefore, the first thing to note is that only the latest released versions of the code were transferred. For instance, JSF 2.3 was transferred as a snapshot from its master branch. JSF 2.2 and earlier versions remain at their original location and are not maintained or supported by the Eclipse Foundation. After the transfer of the source code, all the code was built using Eclipse build servers, and the result was staged to a Maven repository. The API JAR files had their Maven group ID changed from javax.* to jakarta.*, indicating that they are the build artifacts produced by Eclipse. From these, a new build of GlassFish was produced, and against this build the original Java EE 8 TCK was run. After the build passed the TCK tests, proving that all the code was transferred successfully, it was released as GlassFish 5.1. By the way, the initial release of the APIs under the Jakarta group ID are Java EE 8 certified, not Jakarta EE 8 certified. For example, jakarta.faces:jakarta.faces-api:2.3.1 is identical to javax.faces:javax.faces-api:2.3 and both are Java EE 8 certified, but the first is built from github.com/eclipse-ee4j and the latter is from github.com/javaee. Stage 2: Transfer TCK code, set up a new specification process, define new terms, and release a rebranded build. The second stage involved transferring the TCK and building new binaries from it for Jakarta EE 8 certification. A new certification process was set up: the Jakarta EE Specification Process (JESP). Also, a new specification license was created: the Eclipse Foundation Technology Compatibility Kit license. In this stage, new simplified and more-consistent names were created for all specifications. The new names all start with Jakarta and are followed by a simple description of the specification, avoiding inconsistent filler words such as architecture, api, and service. The old and new terms are shown in Table 1. Table 1. Old Java EE 8 terms compared to new Jakarta EE 8 terms The Javadoc for all APIs was updated in this stage to reflect the new terms, and the resulting API JAR files were relicensed and then tested against GlassFish 5.1 with the rebranded TCK that was built from the transferred TCK source code. All this was done following the new JESP specification process. The resulting API JAR files were all released with near-empty placeholder specification documents. These combined constitute Jakarta EE 8. For the individual JAR files, this means that this stage is the third release of technically the same API, the second release using the Maven Jakarta group ID, and the first release that’s Jakarta EE certified. Table 2 shows an example for JSF/Jakarta Faces. Table 2. Example showing the JAR files for JSF and Jakarta Faces (view larger image) There are two extra things to notice here. The first is that for Jakarta EE 8, there wasn’t a corresponding GlassFish release, although GlassFish 5.1 was certified for Jakarta EE 8 in addition to the existing Java EE 8 certification. The second is that, as mentioned above, Jakarta EE 8 was released with essentially empty specification documents. The reason for this is the large amount of time it takes to legally clear and transfer those documents, and this simply was not finished in time for the Jakarta EE 8 release. For now, users (nonimplementors) of the technologies can read the evaluation version of the corresponding Java EE 8 documents. Updating to the Jakarta EE versions of the APIs is the first small step users can take to prepare themselves for the upcoming larger changes. In a Maven project, doing that is mostly as simple as replacing this: <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>8.0</version> <scope>provided</scope> </dependency> With this: <dependency> <groupId>jakarta.platform</groupId> <artifactId>jakarta.jakartaee-api</artifactId> <version>8.0.0</version> <scope>provided</scope> </dependency> Or, when individual dependencies are used, replacing this: <dependency> <groupId>javax.faces</groupId> <artifactId>javax.faces-api</artifactId> <version>2.3</version> <scope>provided</scope> </dependency> With this: <dependency> <groupId>jakarta.faces</groupId> <artifactId>jakarta.faces-api</artifactId> <version>2.3.2</version> <scope>provided</scope> </dependency> Because the APIs are essentially identical, there should be few issues after this update. Note, though, that Maven does not see the two dependencies as related with one being newer than the other. For Maven, there are two totally different dependencies, and Maven will happily include both of them. This can happen, for instance, when a top- level dependency transitively brings in a Java EE dependency. Prior to the update to Jakarta, a transitively introduced javax.faces:javax.faces-api:2.2 would be overridden by, for example, a top-level javax.faces:javax.faces-api:2.3. When that top-level dependency is changed to jakarta.faces:jakarta.faces-api:2.3.2, the 2.2 dependency will no longer be overridden and Maven will use them both, leading to all sorts of problems. If the transitive inclusion can’t be updated, this issue can typically be fixed by using exclusions, for example: <dependency> <groupId>com.example</groupId> <artifactId>foo</artifactId> <scope>provided</scope> <exclusions> <exclusion> <groupId>javax.faces</groupId> <artifactId>javax.faces-api</artifactId> </exclusion> </exclusions> </dependency> That brings me to the final step in the process. Stage 3: Transfer and update the specification documents, prune the specifications, change the API package name, and release JDK 11. The final step of the transfer, which is currently in process and set to complete later this year, includes transferring the specification document source code (mostly in AsciiDoc).