Overview

We've done a lot of good work on WildFly Preview in the last year but as planning work in Jakarta on EE 10 starts to get underway I hope we can make a lot more progress, specifically in increasing the number of 'native' jakarta.* EE 9.1 components' we use. This will allow us to focus on EE 10 dev when the time comes. Ideally by the time WF 26 comes out in the Dec/Jan timeframe we'll have eliminated the transformation of artifacts that we do when provisioning a server with the wildfly-preview feature pack, and instead we'll be using native jakarta artifacts available in maven central or repository.jboss.org.

This thread is meant to drive discussion about how to do this. WF devs of course don't control many projects that provide components, so for those this discussion would be more informational for the WF subsystem leads who interact with those communities.

By a 'native jakarta component' I mean one whose compiled artifacts use the jakarta namespace and otherwise support EE 9.1.

If at all possible it should also provide a matching -sources jar, to help provide a better debugging experience. This is particularly important for components against which WildFly users would compile applications.

For artifacts we package in modules that we don't mark with jboss-api="private" or jboss-api="unsupported", it should also provide a matching -javadoc jar. 

Priority

More urgent are components against which other WF components compile, where EE classes are part of the API compiled against. The closer a component is to the root of a dependency chain, the higher the priority, as having a native component makes it easier for other components to do their work.

EE API spec forks are not necessarily urgent unless WF itself intends to use that fork instead of the Eclipse project. (We need to formally resolve which EE 9+ spec forks WF needs, which is a separate topic. WF Preview is currently using fewer spec forks than standard WF.)

Approaches

There are a number of approaches a project can follow to produce native components, each with pros and cons

1) Branching and updating code.

This obviously works, but it comes with a big cost if there will be continued demand for updates using the javax.* namespace. IMHO it is pretty likely that there will be continued demand for many components to provide updates to their javax.* releases.

I had been thinking that during the WF 26 cycle WF itself might follow this approach, but I'm increasingly thinking we should follow one of the other approaches.

An issue with this is it means you are compiling, which means you need jakarta.* components to compile against, which may not be available.  If not you can try Stuart Douglas's optimus project to generate during your build transformed deps to build against. James Perkins tells me he is working on something along these lines to add to wildfy-extras/batavia.

2) Adapters

Some components might be able to support both javax and jakarta in the same code base abstracting away the EE API and providing adapters. Not much to say about this; you know better if it fits your component.

3) Bytecode transformation with a maven qualifier

Here you update your pom and add a plugin execution that transforms that maven module's normal javax binary to produce another artifact with a different qualifier.

The key downside to this is it doesn't produce matching -sources.jar or -javadoc.jar artifacts. So I don't think it should be our preferred approach.

Jackson 2.12 did this for a few artifacts, e.g.

https://github.com/FasterXML/jackson-jaxrs-providers/blob/2.12/json/pom.xml#L115

They used the shade plugin. This can also be done using wildfly-extras/batavia or Eclipse Transfomer directly.

4) New maven module, transform all artifacts

Create a new maven module to pair with your javax-based module. Add "-jakarta" to the artifactId. Module just has a pom. Pom uses plugins that call the Eclipse Transformer to transform *all* the artifacts from module it is paired with (binary jar, -sources.jar, -javadoc.jar)

Narayana did this -- see https://github.com/jbosstm/narayana/pull/1824/files

Hibernate does this for its 5.5 series. This is a gradle build.

https://github.com/hibernate/hibernate-orm/blob/main/hibernate-core-jakarta/hibernate-core-jakarta.gradle#L100

5) New maven module, transform source and build

Create a new maven module to pair with your javax-based module. Add "-jakarta" to the artifactId. Module just has a pom. Use the Eclipse Transformer to transform the unzipped source from the javax module, writing it to generated-sources in the jakarta.* module. Then build the jakarta.* artifacts from the generated source.

Examples of this:

https://github.com/wildfly/wildfly/pull/14485
https://github.com/jboss/metadata/pull/142

A pro (and con) of this approach is you can also transform src/test and then run the tests. (A con because it can send you down rabbit holes getting tests to work. That can reveal things that are good to know though.)

Another con is again this means you are *compiling* which means you may need jakarta.* deps to compile against. 

6) Don't transform

There may be some components that use EE APIs internally but objects don't leak in or out. A possible example would be JSON where a component might want to deal with JSON for completely internal purposes, and used EE JSON for convenience. In theory WF could provide javax JSON via internal modules and the components using it could skip transformation.

I did a similar thing with H2, which provides some servlet integration classes that WF does not support. I see no reason to worry about a native jakarta.servlet H2 so I sent up a PR to disable transformation of it:

https://github.com/wildfly/wildfly/pull/14313


Lots to digest here; discussion is very much welcome.


Best regards,
Brian