Jakarta EE Without javax: The World Won't End This Time Either
If you missed the news back in 2017, Oracle is donating the Java EE specification to the Eclipse foundation. This decision has followed a rather long period of hibernation in the specification process where people rightfully suspected a loss of strategic interest in Java EE by Oracle. At first, the decision to donate the specification was well-met by the Java EE and broader Java community. Without Oracle slowing down the process, those involved in Java EE could once again attempt to close up to non-standardized APIs. Until today, the donation process was, however, incomplete due to Oracle and the Eclipse Foundation being in disagreement about several details of the donation being made.
While turning over all intellectual property, Oracle was less generous when it comes to the use of its Java brand within the specification’s new home. Java EE does, of course, contain the name of the open-source, yet trademark-protected platform that is owned by Oracle. And this renders a problem in a legal context: If you grant a third party the use of your brand's name, you have yielded rights to restrict it in the future. To make things worse, you are potentially weakening your position in court when it comes to lawsuits regarding your brand. With the history of Oracle and Google arguing about Java licensing for years, one could, therefore, have anticipated that branding would be a difficult discussion point. And without pretending to know much about international trademark law, I was told by people more involved that "use it or lose it" is a good enough approximation for understanding the general motto of such disagreements. As a first result, the specification was therefore renamed from Java EE to Jakarta EE to avoid a clash of interests.
The real shocker for the newly formed Jakarta EE community was, however, yet to come. After months of discussing formalities of the donation, the Eclipse Foundation learned that it could not assume ownership of the current javax namespace that hosts the APIs that are defined within Java EE. Instead, this namespace is now planned to be hibernated for all donated APIs. Any new API that will be created within the specification process of Jakarta EE is therefore supposed to be hosted within a new namespace to avoid infringing Oracle's trademark.
At this point, it is important to clarify what this means. Jakarta EE and the Eclipse Foundation are not prohibited from using the javax namespace or implementing its API. Neither will APIs that currently exist be deleted. But any API that is created or updated within the newly formed Jakarta EE specification process will need to live in a new namespace that is most likely imitating the one in existence but with jakarta as its prefix instead of javax. As an example, if a new method was to be added to the javax.servlet.Servlet interface, the next version of the servlet specification would need to publish a new interface named jakarta.servlet.Servlet instead of adding this method to the existing API.
I Am Not a Java EE User. Why Would I Care?
Formally, the Java platform, as most people know it, is split into two parts. The first part is Java SE, where all APIs are defined within packages that are prefixed with java. In addition to that, Java EE specifies extending APIs within the javax namespace. Those APIs do not imply a particular implementation, but only define behavior that is implemented by different vendors of Java EE-compliant components.
In this context, Java EE is a blanket term for several API specifications that are not dependent on one another. As an example, the Java messaging specification (JMS) defines an API for interacting with message queues, whereas the Java servlet specification defines an API for dispatching calls to a web server. In practice, no Java EE application runtime that I know of implements the entirety of APIs that are defined within the Java EE specification process. And some Java frameworks even focus on implementing a single specification. As an example, the Jetty web server only implements the Java servlet specification. Therefore, if you are using Jetty via Spring Boot, you are formally a user of Java EE, even if you are not interacting with the specification directly or consider yourself a Java EE user.
Despite this formal distinction, you have probably encountered Java EE and its javax namespace even if you only ever programmed vanilla Java without including any external dependencies. This is because of select Java EE APIs being bundled with the standard image of the JVM. In addition to the API, the JVM also ships a default implementation of this API to offer users the convenience of solving common tasks without any additional effort. As an example, JAXP is a Java EE specification that defines an API for processing XML in Java. With XML-processing being such a common task, especially on the enterprise-oriented Java platform, its inclusion was a reasonable choice. For JAXP, its assumed common usage is still factual today, but other JVM-bundled Java EE specifications did not age equally well. As an example, SOAP messaging is no longer the first choice for most Java developers such that the JVM-bundled JAX-WS implementation has become dead weight for the majority of users. In order to cut down on the JVM footprint, and with the introduction of the Java module system in Java 9, several Java EE APIs were moved to deprecated modules that are scheduled for removal in a future release. Of course, this does not imply that a module's API itself is deprecated. JAX-WS is still alive and actively used by many. But as a result of this module deprecation, JAX-WS needs to be added as an explicit dependency by those that want to continue using it in a future Java release.
In our age of running microservices on virtualized hardware, a reduced JVM footprint has become an obvious goal of evolving the JVM. But removing Java EE API from the base JVM image has another advantage. By asking users to include an explicit dependency on Java EE API, upgrading the Java runtime and Java EE are no longer tied together. Until Java 8, managing such version interdependencies has always been tedious. This is especially true if you do not control the exact version of the JVM that you are deploying your applications to. Until Java 8, the JVM only allowed you to override an implicit Java EE dependency by placing a JAR file into the JVM's extension folder. But this is, of course, problematic when you are sharing a JVM installation with other Java processes that would also be affected. Also, you are still required to have some control over the JVM installation being used. To remedy this problem, the Java module system does no longer resolve the deprecated Java EE modules by default what makes it possible to include an explicit version with the JVM despite the continued on-demand bundling while also offering a simple way of activating legacy compatibility.
To make things even more complicated, a small subset of Java EE APIs grew into Java SE in a way that does not allow their simple separation. As an example, the JDBC specification is split into "client-side" and "server-side" requirements where the former bit formally belongs to Java SE whereas the latter is part of Java EE. This distinction comes from the original Java philosophy where one would use Java SE for user-facing desktop applications but Java EE for server applications that are used by multiple concurrent users. In this spirit, the JDBC Connection interface is for example defined in the java.sql package. After all, a desktop user might, of course, want to connect to a database. On the other hand, the JDBC DataSource interface is defined in the javax.sql package as connection pooling was considered a requirement only for multi-threaded server applications. From today's perspective, this separation does of course no longer make much sense but the namespace and formal distinction remains even today.
Of course, it would not be meaningful to have the JDBC API evolve separately within both Java SE that is managed by the OpenJDK project and by Jakarta EE that is now managed by the Eclipse Foundation. Therefore, not all parts of the Java EE specification were donated to Eclipse such that the javax.sql namespace will be retained for the JDBC API that is now considered to be a part of only Java SE. Other examples of such API retention are the JMX API which relies heavily on native JVM-support. And of course, all other APIs that were always considered to be part of Java SE such as the Swing API that also ended up in the Java extension namespace will remain in their original packages.
What About Backwards Compatibility?
The important thing to keep in mind is that no currently existing javax API will disappear, neither today or in the future. Personally, I also expect the specifications that are now part of Jakarta EE to support the javax namespace for many years to come. As a matter of fact, dealing with multiple namespaces is nothing new to most Java EE implementations but has always been an important topic to deal with. The Hibernate library, for example, has already successfully completed a similar migration when gradually replacing its own annotations with those defined by the JPA specification. In another example, the Spring framework supports the Java EE CDI specification in parallel to its native annotations. Doing so, it is, for example, possible to request a bean injection by using either the javax.inject.Inject annotation or Spring's native Autowired annotation. Once the Inject annotation is transferred to the jakarta package, I would therefore expect the Spring framework to support both the Java EE and Jakarta EE namespace, as I also expect it from other implementers of Java enterprise APIs.
With Jakarta EE being the successor of Java EE, I would neither expect this support to be overly costly to implement or maintain, as application server vendors can simply implement Jakarta EE wrapper classes that delegate to the now outdated Java EE API. For example, a Java EE servlet can internally be treated as a Jakarta EE servlet by defining a wrapper class similar to the following:
public class LegacyServlet implements jakarta.servlet.Servlet {
private final javax.servlet.Servlet delegate;
public LegacyServlet(javax.servlet.Servlet delegate) {
this.delegate = delegate;
}
@Override
public void service(jakarta.servlet.ServletRequest req, jakarta.servlet.ServletResponse resp) {
delegate.service(new LegacyServletRequest(req), new LegacyServletResponse(resp));
}
}
This should be fairly simple if Jakarta EE targets (logical) backwards compatibility to the current specification and API. If this principle is adhered to, this would also require users of the API to only update to the Jakarta namespace in case that they want to take new features into use what already requires code changes. I would therefore expect the changed namespace not to affect future Jakarta EE users too much, but to mainly be the concern of those implementing its APIs. Looking back to other more fundamental changes to the Java platform in the past, this was also true when, for example, the Java module system was introduced, which mostly concerned library and framework developers but rarely end users of Java.
Of course, support for both namespaces will never be universal, especially not in the long run, and therefore users of Java EE APIs will need to react to the transition eventually. Given that the specification retains binary compatibility of its API with the exclusion of the change in namespace prefix, I believe that porting software should be easy to overcome and should even be automatable. Any Java class references its imported types in each class file's constant pool. It would be trivial for a tool to patch all relevant type references in all constant pools of an artifact with the new jakarta prefix. Doing so, legacy users of Java EE could avoid source code changes for their applications under passive maintenance and only apply such changes after compilation, or even patch an artifact during deployment.
What Drives Oracle?
I am of course a software consultant and not an expert of international trademark jurisdiction. Neither do I have any insights into Oracle's decision-making process. Therefore, please take this last section as educated speculation mixed with my personal opinion rather than a summary of facts.
Several voices in the Java community are currently accusing Oracle of acting against the interest of Java and its users by restricting the use of the javax namespace. There have also been heated debates in the Eclipse foundation to the point where it was suggested that the donation of Java EE in this way might be rejected due to its incompatibility with the goals and values of the organization.
Given that this change does impose significant work on the users of Java, one can of course quickly arrive at this opinion. I can, however, not imagine that Oracle took this decision lightly. Oracle is and has been investing heavily in the Java platform – Java has rarely been as alive as it is today – but it has also changed its strategic orientation. To me, the idea that Oracle does “not care” about the Java community while making these investments simply does not fit.
So what do I think motivated this decision? To me, the restriction has little to do with Java EE but is about Oracle protecting its interest in Java SE. At the end of the day, Oracle is investing in Java to turn a profit. And by allowing the use of its trademark, Oracle would be giving up a share of the control of its brand, which sets this goal into jeopardy. Of course, Oracle is relying on Java for its own products and also maintains it for this reason. But at the same time, the company is attempting to create a strategic model that justifies the funding of the many hundreds of full-time and highly qualified employees that work on Java.
Oracle is quite obviously pushing into selling cloud solutions, and given the company's current dominance in runtimes and databases, in addition to its deep pockets, I believe that their chances to gain significant market share in this field are better than many people anticipate. Another indication of Oracle's is its investments into the Graal VM and its compiler, which also offers the Java language a much broader scope of application in resource-constrained environments, like containers.
But while investing in certain areas, Oracle is surely also looking into ways of cutting costs, like terminating ventures that are no longer of strategic interest or not sufficiently profitable. And while it saddens users – including myself – that a successful project team like that of Java flight recorder is laid off, it makes sense given that the vast majority of Java developers are not asking for such tooling. I believe that Java EE did not fit into Oracle’s plans or cost profile for the platform and suffered a similar fate.
In this light, Oracle probably considered a trade-off between giving up the specification versus donating it for other people to maintain. And while the choice to donate Java EE might seem to come without costs, Oracle is, of course, taking a risk by making this donation. By allowing competing organizations to continue their efforts in Java EE, these efforts might also strengthen their ability to compete against Oracle in the Java SE segment. This is especially true with Red Hat and IBM — which are also competing in the market for cloud solutions. By protecting its branding rights, Oracle is simply aiming to reduce the risk that Java EE is weaponized by a competitor to fight for Java SE marketshare in the future. And to be fair, Oracle had offered a way for the Eclipse foundation to continue using the javax namespace. However, this would have required the foundation to restrict itself to bundling its products with Java SE-certified implementations of the JVM rather than, for example, its own IBM-donated OpenJ9. Doing so, Oracle would have retained sufficient control of its brand, but at the same time, it is very understandable that signing such a broad agreement was not in the interest of the foundation. It just was not meant to be and in this light, one could even argue that Eclipse was the wrong choice for receiving the donation of Java EE in the first place.
What Comes Next?
In the open source community, we discuss loudly and often that our work is underfunded. And while the lacking profitability is a problem for individual developers hacking away their nights, it is of course also an issue for large corporations, be it Oracle or any other company involved in the current discussion. In my opinion, by Oracle donating the intellectual property of Java EE, the Java community was already handed over the most important part of the specification and we should focus on what we have and not get overly distracted by the strings attached. Personally, I’d worry more about the future of Java if Oracle had lost interest in the Java brand instead of taking its stand.
As for Jakarta EE, I do not think that the coming namespace migration is the biggest problem the specification is facing. Many developers were frustrated with the dustiness of Java EE even before the recent stagnation period. In my opinion, the problem is part of the process. In reality, a Java EE specification is often derived from a leading framework’s implementation. If another framework wanted to reinvent how the same problem can be solved with a better API, it needs to face the constant criticism that it does not adhere to the standard. This all despite the fact that this standard was typically nothing but a snapshot of a previous best practice. For this reason, I hope that Jakarta EE can focus on its evolution instead of holding too much onto its past. With a compelling offering of a state-of-the-art API, I would not worry too much about adjusting my code if it saved me from implementing iterations of a minimally altered jakarta.servlet.Servlet API.