Skip to content

Perform the jakarta EE migration#414

Merged
Stewori merged 9 commits intojython:masterfrom
ohumbel:feature/jakartaee
Mar 2, 2026
Merged

Perform the jakarta EE migration#414
Stewori merged 9 commits intojython:masterfrom
ohumbel:feature/jakartaee

Conversation

@ohumbel
Copy link
Copy Markdown
Contributor

@ohumbel ohumbel commented Feb 4, 2026

The goal is to replace javax.servlet with jakarta.servlet.

Some application containers like WildFly refuse to start up if a .jar file on the classpath contains a class in a package javax.servlet.
This pull request will enable embedding Jython in modern applications.

@Stewori
Copy link
Copy Markdown
Member

Stewori commented Feb 4, 2026

This is related to issue #382, but does not seem to take the discussion into account (nor reference the issue in the description). As it stands, the fix is not backwards compatible and as a drop-in replacement might break existing setups without warning or deprecation path or anything. At very least, such a change should induce a change in maven coordinates, e.g. to jython-jakarta-standalone etc. Compared to that, I would prefer the solution I suggested in #382. If you see it differently, please explain why the approach should be preferred over the suggested solution.
That said, why would we base this on jakarta-api 9.0? Jakarta 11 is the current release. Given Jython's infrequent releases and the still manual work of adding the dependencies, it should be updated as far as possible. Another question: Why jakarta-api and not jakarta-servlet any more? AFAIK, best practice is to narrow dependencies as far as possible. Jython does not depend on any other Jakarta module. IMO jakarta.servlet-api/6.1.0 would be the correct current depndency as of this writing (6.2.0 is in M1 phase).

@ohumbel
Copy link
Copy Markdown
Contributor Author

ohumbel commented Feb 6, 2026

Why jakarta-api and not jakarta-servlet any more? AFAIK, best practice is to narrow dependencies as far as possible.
Jython does not depend on any other Jakarta module. IMO jakarta.servlet-api/6.1.0 would be the correct current dependency as of this writing (6.2.0 is in M1 phase).

That is correct - jakartaee-api is too broad. I was able to replace it with jakarta.servlet-api-5.0.0.

Newer versions do not compile with java 8.

jakarta.servlet-api-6.1.0:

/jython/src/org/python/util/PyServlet.java:13: error: cannot access jakarta.servlet.ServletContext
import jakarta.servlet.ServletContext;
                      ^
  bad class file: /.gradle/caches/modules-2/files-2.1/jakarta.servlet/jakarta.servlet-api/6.1.0/1169a246913fe3823782af7943e7a103634867c5/jakarta.servlet-api-6.1.0.jar(jakarta/servlet/ServletContext.class)
    class file has wrong version 55.0, should be 52.0

jakarta.servlet-api-6.0.0:

/jython/src/org/python/util/PyServlet.java:13: error: cannot access jakarta.servlet.ServletContext
import jakarta.servlet.ServletContext;
                      ^
  bad class file: /.gradle/caches/modules-2/files-2.1/jakarta.servlet/jakarta.servlet-api/6.0.0/abecc699286e65035ebba9844c03931357a6a963/jakarta.servlet-api-6.0.0.jar(jakarta/servlet/ServletContext.class)
    class file has wrong version 55.0, should be 52.0

Since Jython targets java 8, there is only a narrow range of external libraries which can be used. I suspect that this range will get even more narrow with the progress of the java ecosystem.

@ohumbel
Copy link
Copy Markdown
Contributor Author

ohumbel commented Feb 6, 2026

That said, why would we base this on jakarta-api 9.0? Jakarta 11 is the current release. Given Jython's infrequent releases and the still manual work of adding the dependencies, it should be updated as far as possible.

I would love to offer newer versions of external libraries. But the situation is likely the same as the one for jakarta.servlet-api: Recent versions require a higher version of java.

@ohumbel
Copy link
Copy Markdown
Contributor Author

ohumbel commented Feb 6, 2026

This is related to issue #382, but does not seem to take the discussion into account (nor reference the issue in the description).

I really forgot to reference the issue #382. That is my fault, sorry for that.

Please let me explain in a following comment why I think the solutions suggested in #382 are not workable. I need some time to express this the right way.

@Stewori
Copy link
Copy Markdown
Member

Stewori commented Feb 6, 2026

Alright, thank you for addressing this. I am not sure whether Jython does actually still support Java 8. I vaguely remember that @jeff5 once mentioned the support was dropped. (I used to feel that we should be more explicit about these decisions, but it turned out to be tedious to keep track.) In that case, a newer jakarta.servlet version might be feasible.

@ohumbel
Copy link
Copy Markdown
Contributor Author

ohumbel commented Feb 17, 2026

Alright, thank you for addressing this. I am not sure whether Jython does actually still support Java 8. I vaguely remember that @jeff5 once mentioned the support was dropped. (I used to feel that we should be more explicit about these decisions, but it turned out to be tedious to keep track.) In that case, a newer jakarta.servlet version might be feasible.

The build files are explicit:

build.gradle
65: sourceCompatibility = '1.8'
66: targetCompatibility = '1.8'

build.xml
94:      <property name="jython.java.version" value="1.8" />
95:      <property name="jdk.source.version" value="1.8" />
309:     <property name="jdk.target.version" value="${jython.java.version}" />
310:     <property name="jdk.source.version" value="${jython.java.version}" />

@ohumbel
Copy link
Copy Markdown
Contributor Author

ohumbel commented Feb 17, 2026

As it stands, the fix is not backwards compatible and as a drop-in replacement might break existing setups without warning or deprecation path or anything.

Maybe it is worth mentioning that the latest released Jython version prevents users from upgrading their own projects to jakarta.
The jakarta community decided to do a breaking change instead of a long period of suffering between versions. This decision was made some years ago, and the community has moved forward since then.
I am convinced that there is no other way than breaking backwards compatibility (to a serlvet version that is not maintained any more since years...).

At very least, such a change should induce a change in maven coordinates, e.g. to jython-jakarta-standalone etc. Compared to that, I would prefer the solution I suggested in #382. If you see it differently, please explain why the approach should be preferred over the suggested solution.

The example of WildFly makes it clear that there can be no hybrid solution (WildFly does not start if there is a reference to the old javax.servlet package on the classpath).
The only solution can be two different artefacts, one supporting the old world, one the new.
I still am in favour of Jython 2.7.(n) still supporting the old javax.servlet, and Jython 2.7.(n+1) supporting javax.servlet. Here they are, the above mentioned two artefacts.
I think the maintenance burden of supporting two different artefacts at the same time is much too high. At least I am not willing to dedicate my time to a very, very old servlet version.

Given Jython's infrequent releases, this burns down to a documentation issue.

That are my thoughts, directed to the future. Of course I know - and respect - that one could see it differently.

@Stewori
Copy link
Copy Markdown
Member

Stewori commented Feb 17, 2026

Okay, thank you for the explanation. I did not know that WildFly blocks startup in this manner (and then, it's the norm for other frameworks too). In that light, I'd suggest the following: Do it like it currently stands, but relocate org.python.util.PyServlet, org.python.util.PyFilter and org.python.util.PyServletInitializer to a new package org.python.servlet. That should work fine and should not be asked too much. It would use the occasion to declutter the org.python.util package and we have the option to offer a separate back-compatibility artifact consisting just of the old org.python.util.PyServlet, org.python.util.PyFilter and org.python.util.PyServletInitializer. Someone could include this artifact on top without name conflict since the packages were adjusted. An old javax.servlet-based WildFly would not break if jakarta.servlet is referenced I suppose. So, this relocation may allow to restore workability of a new Jython release as a drop-in replacement for an old setup by adding a potential backwards artifact on top. I'm not asking to actually provide the backwards artifact, perhaps we actually won't. I just ask to keep that door open by relocating the servlet classes (to a package name that would have been more suitable than plainly util in the first place).

@ohumbel
Copy link
Copy Markdown
Contributor Author

ohumbel commented Feb 17, 2026

relocate org.python.util.PyServlet, org.python.util.PyFilter and org.python.util.PyServletInitializer to a new package org.python.servlet.

That's perfectly fine - I start working on this (converting this PR to a draft meanwhile)

@ohumbel ohumbel marked this pull request as draft February 17, 2026 15:31
@ohumbel
Copy link
Copy Markdown
Contributor Author

ohumbel commented Feb 17, 2026

An old javax.servlet-based WildFly would not break if jakarta.servlet is referenced I suppose.

I did not test that, but I am quite convinced that an old WildFly has no knowledge about the later meaning of jakarta.servlet.

So, this relocation may allow to restore workability of a new Jython release as a drop-in replacement for an old setup by adding a potential backwards artifact on top

Exactly, that could be done. But I really hope that this won't be necessary.

…servlet

Adjust the inline documentation accordingly.
@ohumbel
Copy link
Copy Markdown
Contributor Author

ohumbel commented Feb 17, 2026

Before I push, I use to run the gradle build and the regrtest-ci ant target in a shell with java 8:

➜  jython git:(feature/jakartaee) ✗ sdk use java 8.0.482-tem 
Using java version 8.0.482-tem in this shell.

➜  jython git:(feature/jakartaee) ✗ ./gradlew build
:
:
BUILD SUCCESSFUL in 36s
13 actionable tasks: 7 executed, 6 up-to-date

➜  jython git:(feature/jakartaee) ✗ ant -noinput -buildfile build.xml regrtest-ci
:
:
     [exec] 383 tests OK.
     [exec] 2 tests skipped:
     [exec]     test_codecmaps_hk test_curses

regrtest-windows-ci:

regrtest-ci:

BUILD SUCCESSFUL
Total time: 18 minutes 8 seconds
➜  jython git:(feature/jakartaee) ✗ 

This is on an Intel Macbook pro running macOS Tahoe 26.3.
On ubuntu, the results are comparable.
On windows, I do not know.

@ohumbel
Copy link
Copy Markdown
Contributor Author

ohumbel commented Feb 17, 2026

Your second comment about Java 8 only appeared in my inbox.
I quote it here for completeness:

Re Java 8: I suspect, 65: sourceCompatibility = '1.8' / 66: targetCompatibility = '1.8' were just forgotten. It's well possible that Jython does actually call Java 9 API but keeps class-file format Java 8 compatible. Why? No reason. The real question is whether tests pass on Java 8. If they do (I doubt it), then hooray, it's still Java 8 compatible. I think we removed Java 8 from the CI (because it wasn't offered any more). I currently do not have Java 8 installed so I could test it myself.

Temurin (by Adoptium) still offers Java 8 for all major platforms. On Mac and ubuntu, I use sdkman (https://sdkman.io/install/) to manage all kinds of Java versions.

But I admit that on my company and personal forks, I use to build with Java 21. Which is much faster, by the way.

@ohumbel ohumbel marked this pull request as ready for review February 17, 2026 17:25
@Stewori
Copy link
Copy Markdown
Member

Stewori commented Feb 17, 2026

I deleted the comment because I checked our CI config and found that Java 8 is indeed still tested. Must have mixed-up the situation with Java 7, sorry for the wrong alert.

@Stewori
Copy link
Copy Markdown
Member

Stewori commented Feb 17, 2026

Okay, I reviewed the changes again and find that
tests/modjy/java/org/python/util/PyFilterTest.java and tests/modjy/java/org/python/util/PyServletTest.java should consistently be relocated to package org.python.servlet (moving the files from tests/modjy/java/org/python/util to tests/modjy/java/org/python/servlet respectively). Im not familiar with the functioning of test/modjy. Would this relocation need adjustment elsewhere?

@ohumbel
Copy link
Copy Markdown
Contributor Author

ohumbel commented Feb 19, 2026

Okay, I reviewed the changes again and find that
tests/modjy/java/org/python/util/PyFilterTest.java and tests/modjy/java/org/python/util/PyServletTest.java should consistently be relocated to package org.python.servlet (moving the files from tests/modjy/java/org/python/util to tests/modjy/java/org/python/servlet respectively).

Done with the last commit.

Would this relocation need adjustment elsewhere?

Yes, I found references in one other .java file.

Im not familiar with the functioning of test/modjy.

Me neither. I vaguely remember it being "added on top" in the early days...
But I do not think that the tests are alive - I just discovered the separate build.xml and readme.txt. They look quite abandoned to me.

But if they ever would be resurrected, the packages are right.

@Stewori
Copy link
Copy Markdown
Member

Stewori commented Feb 19, 2026

Note to whoever reads this discussion:
Whenever a binary file is modified I routinely doublecheck that the file is actually the file it is supposed to be. As expected, I can confirm (via cmp) that in this PR the provided jakarta.servlet-api-5.0.0.jar is binary identical to the one distributed at https://repo1.maven.org/maven2/jakarta/servlet/jakarta.servlet-api/5.0.0

@Stewori
Copy link
Copy Markdown
Member

Stewori commented Feb 19, 2026

Perfect, tests pass, changes look good, we're ready to go. Since the next release is not scheduled, I think we have time to let this PR rest for a couple of days before merging, so other devs have a final chance to intervene if there are any concerns (@jeff5 @wfouche @tbpassin). (This is just another safety measure for me since I haven't pushed the merge button on Jython for a while.) If nobody speaks up, I will merge it on next Wednesday/Feb 25th.
@ohumbel Thank you for the work on this on for your patience!

@tbpassin
Copy link
Copy Markdown

Your second comment about Java 8 only appeared in my inbox. I quote it here for completeness:

Re Java 8: I suspect, 65: sourceCompatibility = '1.8' / 66: targetCompatibility = '1.8' were just forgotten. It's well possible that Jython does actually call Java 9 API but keeps class-file format Java 8 compatible. Why? No reason. The real question is whether tests pass on Java 8. If they do (I doubt it), then hooray, it's still Java 8 compatible. I think we removed Java 8 from the CI (because it wasn't offered any more). I currently do not have Java 8 installed so I could test it myself.

Temurin (by Adoptium) still offers Java 8 for all major platforms. On Mac and ubuntu, I use sdkman (https://sdkman.io/install/) to manage all kinds of Java versions.

But I admit that on my company and personal forks, I use to build with Java 21. Which is much faster, by the way.

Openlogic has a compatible version of JDK 8+. I was able to build the 2.7.4 version with it. At java 9 and above, there are apparently some changes with how call arguments are handled that caused the build to succeed but the Jython jar file to fail to run in my Tomcat webapp.

@tbpassin
Copy link
Copy Markdown

Tomcat 9, 10, 11 weren't compiled with the same version of Java. V9 has remained with java 8, but Tomcat v10 is said to have been compiled with java 11; I'm not sure about Tomcat v11. There is also some change in Java v25 that is not always backwards compatible.

Different Linux distros provide different java versions through their package managers. All the version mix-and-match differences can make it hard to make a single Jython jar file work for everyone.

I think that going forward, the minimum Java version should be 17, or even 21. It won't be backwards compatible for some people, say those who are running Tomcat v9 with Java v8. But their systems have already been working and will continue to work as long the Jython 2.7.4 or earlier jar file remains available.

So the easiest approach to the javax/jakarta namespace issue, and the java version issue, seems to be simply to make sure the the current version of the Jython package will continue to be made available along with newer ones.

@Stewori
Copy link
Copy Markdown
Member

Stewori commented Feb 19, 2026

Issue acknowledged. However, this PR is not the place to address Java version compatibility of Jython as a whole. I think for now it's reasonable to stick to the established compatibility policy. I guess the next release is not too far away and I would not like to break Java 8 compatibility on the last meters. I'd suggest to gradually extend tests to Java 17 and 21, perhaps 25, after Jython 2.7.5 release. Then we'll see.

@ohumbel
Copy link
Copy Markdown
Contributor Author

ohumbel commented Feb 20, 2026

@Stewori Thanks for all the review and the recommendations - the current solution is definitively better than the one initially suggested.

@jeff5
Copy link
Copy Markdown
Member

jeff5 commented Feb 20, 2026

My head has been out of Jython (Jython 2 anyway) for a while. I do not know very much about servlets, so I'm grateful we have contributors who do. I have delved very little in that bit of Jython, and possibly done more harm than good.

That said, I've followed the discussion and I AFAICT you have come to a reasonable conclusion I'm happy to let stand.

Thanks @ohumbel and @tbpassin for contributing and @Stewori for challenging thoughtfully. We should have the Java version discussion separately.

Copy link
Copy Markdown
Member

@jeff5 jeff5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just trivia.

@Stewori
Copy link
Copy Markdown
Member

Stewori commented Feb 22, 2026

It also occurred to me that his change must get a descriptive NEWS item and we should announce the change on the mailing list asap. IMO, the news entry can be several lines long for an impactful change like this, should mention the relocation and that users might need to adjust their config accordingly. I may draft the entry later and place it here for review.

@Stewori
Copy link
Copy Markdown
Member

Stewori commented Feb 25, 2026

Okay, sorry for the delay. Would this text work?

New Features

    - Servlet support is updated to use the jakarta namespace. As part of this
      change, the classes org.python.util.PyServlet, org.python.util.PyFilter
      and org.python.util.PyServletInitializer have been relocated to a new
      package org.python.servlet. Users should double-check that this change is
      adjusted in their config if necessary.
      The relocation allows adding the old classes (with javax.servlet imports)
      to the classpath on top of jython.jar without name conflict. In many cases
      this should suffice to retain workability of a legacy setup if needed.

@Stewori
Copy link
Copy Markdown
Member

Stewori commented Feb 28, 2026

@ohumbel Can you please add the NEWS entry as part of this PR?
Also please add the line
- [ GH-382 ] Java EE Servlet Namespace Has Been Changed From javax.servlet to jakarta.servlet
in Bugs Fixed section.

ohumbel added 2 commits March 2, 2026 08:01
I am starting to feel really ashamed
@Stewori Stewori merged commit 73524c8 into jython:master Mar 2, 2026
8 checks passed
@ohumbel ohumbel deleted the feature/jakartaee branch March 9, 2026 09:59
iotonio added a commit to BisonSchweizAG/jython that referenced this pull request Mar 11, 2026
* Perform the jakarta EE migration (jython#414)

* Replace javax.servlet with jakarta.servlet
* Move the jakarta.servlet related classes to a new package org.python.servlet
* Move modjy's PyFilterTest and PyServletTest to their new package, too
* Update NEWS

* Upgrade jffi to version 1.3.14 with JDK23+ support (jython#409)

* Update NEWS

* highlight jffi update to resolve dependence on sun.misc.Unsafe
* bugs fixed: added older issue regarding javax.servlet to jakarta.servlet namespace change

---------

Co-authored-by: Otmar Humbel <[email protected]>
Co-authored-by: Werner Fouché <[email protected]>
Co-authored-by: Stefan Richthofer <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants