GWT, Java 17, jakarta.servlet, Eclipse, GWT plugin

208 views
Skip to first unread message

Bob Lacatena

unread,
Jun 11, 2024, 6:01:47 PMJun 11
to GWT Users
I am wrestling with a massive effort that has been one stumbling block after another. The core task is to convert a sadly monolithic and archaic app from Java 8 to Java 17.

My current subtask (maybe necessary, maybe not) is to convert everything to use jakarta.servlet rather than javax.servlet, but when I try to declare an import of com.google.gwt.user.server.rpc.jakarta.RemoteServiceServlet, Eclipse just keeps replacing it with the "original" (non-jakarta) path.

I was hoping I could solve this by renaming the gwt-servlet-jakarta.jar file as gwt-servlet.jar, and putting that in war/WEB-INF/lib, but it doesn't change the Eclipse behavior, AND it originally generated an error that the size of that jar did not match the SDK... but after a clean-build that problem (at least) went away.

But my underlying problem is that I have classes that need to extend the RemoteServiceServlet, and access the associated ServletContext, HttpServletRequest, SerializationException and other classes that must all be the jakarta (not javax) versions. 

I can go back to using javax (and I'm not at all certain that the Eclipse embedded Jatty server will use jakarta instead of javax, so maybe jakarta won't work locally anyway)... but then I have to solve a problem where GWT dev mode (with javax) gives me:

Error occurred during initialization of boot layer
java.lang.module.FindException: Module gwt.user not found, required by com.xxxxx.myapp

Or do I have to move into a world where I stop using the so-convenient embedded Jetty and deploy to and run an external server?

Any advice on what to do (or, preferably, a deeper understanding of what is happening) would be greatly appreciated.

Craig Mitchell

unread,
Jun 11, 2024, 8:27:57 PMJun 11
to GWT Users
I would recommend creating a new project with everything that you want to use, get it working how you like, then use that as a template on how you will upgrade your existing project.

For my project that I needed to upgrade from Java 8 to Java 17 (because Google App Engine dropped support for Java 8).  I decided I would go "all-in" and get it onto the latest of everything.  So I needed to switch to use Maven, switch to use a client/server/shared structure, switch to use my own server (I went with Undertow), and switch to use Jakarta.  I also decided to go with Spring Boot (as Google App Engine had examples for that), so I used https://github.com/NaluKit/gwt-maven-springboot-archetype to create a sample project, and used that as a guide on how to upgrade my existing project.  Oh, and I also switched from Eclipse to IntelliJ.

It was a big job and a lot of work, but now everything is running beautifully, so worth it in the long run.

Wejden Mrabti

unread,
Jun 12, 2024, 4:03:01 AMJun 12
to GWT Users
hello!
@Craig it looks great what you have done!
@bob I am working on same migration acutally, It looks that the embedded Jetty in GWT DevMode has been deprecated in GWT 2.11 due to classloader issues and other complexities. To avoid these problems, you can try  transition to a dedicated servlet container like Jetty or Tomcat for both development and production. You can deploy your war file using Docker or a Maven plugin. Ensure that your development environment is set up to deploy to this dedicated servlet container instead of using the embedded Jetty. You can check the updated GWT Getting Started Guide  (https://www.gwtproject.org/gettingstarted-v2.html )for detailed instructions on setting up your project and development environment, making the transition from Java 8 to Java 17 smoother.

tim_mac...@yahoo.co.uk

unread,
Jun 12, 2024, 5:14:50 AMJun 12
to GWT Users
This might help: its a different solution to the issue Craig dealt with.
Its an extension of the gwt multi-module sample with an embedded Jetty,
for Java 11 without Spring.
https://github.com/timmacp/AppEngineGwt/tree/main

Jens

unread,
Jun 12, 2024, 5:27:27 AMJun 12
to GWT Users
1. You do not have to use Jakarta if you want to migrate to Java 17. You can very well stay on javax and first make the JDK transition work
2. GWT's embedded Jetty is always javax because it is version 9.4.xx. The use of GWT's embedded Jetty is officially deprecated and you should use your own Jetty installation (local, docker image, maven/gradle plugin, ...). This is especially true if you want to use Jakarta.
3. GWT 2.11 publishes *-jakarta dependencies that you can use once you start moving to Jakarta.
4. GWT Compiler only supports source level 11 so far

I use Java 11 for GWT client side code and Java 21 + javax for server side code. Needless to say that I have split client, shared and server code into their own projects. This is the recommeneded project layout these days because it gives you dedicated classpaths for each project and the option to use different JDK versions.

-- J.

Thomas Broyer

unread,
Jun 12, 2024, 5:54:58 AMJun 12
to GWT Users
On Wednesday, June 12, 2024 at 11:27:27 AM UTC+2 Jens wrote:
Needless to say that I have split client, shared and server code into their own projects. This is the recommeneded project layout these days

 * checks notes *
I've been advocating for it for more than 12 years now, and had been using it for nearly 2 years already at the time. Java 8 would be released more than 2 years later.

(and note that this is –in terms of filesystem layouts– mostly due to how build tools like Maven and Gradle work, also IDEs if you want smooth integrations –although I'm sure IntelliJ IDEA could adapt to many layouts–; this can be entirely different with Ant or Make, and definitely is different with tools like Bazel/Buck/Pants/etc. Anyway the crux is to understand what you're doing, and why you're doing it, which means understanding how things work: classpaths, build classpaths, GWT Compiler, GWT DevMode/CodeServer, build tools, IDEs, etc.)

Bob Lacatena

unread,
Jun 12, 2024, 11:23:28 AMJun 12
to GWT Users
Thanks for all the replies.  None of them directly addressed my needs, but in combination they all provided enough understanding to help me make some decisions:

Clearly the GWT plugin/installed Jetty are not Jakarta-ready.  I could try to update and rebuild the plugin to make it so (maybe), but I'm so overwhelmed with other chores that I can't afford having that turn into another rabbit hole.  It's easier/safer/wiser to go back to javax.

That still does not solve my larger problem of getting the web app to run... but it seems that must be unrelated to which servlet-api I use, so again, goodbye Jakarta-servlet.

I think I recognized it myself, but the advice to move to away from the embedded Jetty seems unavoidable, as it is deprecated.  It's just so darn convenient.  I also have never found clear examples on how to set to that up, what the pitfalls may be, how it will work, etc.  I'm sure I can figure it out... it's just not something I want to diverge into doing (but it seems at this point I must). 

MEDIUM ASK: Can anyone point me to better documentation or a tutorial or a how-I-did-it-blog post on getting that set up?  Like I said, I can figure it out, I'm sure, but I'd rather do it the quick/easy/no-wasted-time way.

The suggestion of breaking GWT into separate projects has some merit, as part of my entire problem is that, as I said in my intro, I am dealing with a massive, monolithic project that tries to do everything alll in one package.  In general, it would be wise to refactor that into multiple projects (not only around GWT, but other things like the build process, report generation, image generation, the Swing desktop app, and other facets).  Sadly, everything is so intertwined, and there is so much code, that doing so will be a massive effort, and this is just one of many high-pressure/short-timeframe projects on my plate, so I'm going to need to find the best/least-effort path in refactoring to make things work (with a longer-term project of continually refactoring things out).

I may consider falling back to an earlier version of Java, maybe 11, but I'm unsure if that will help.

I may also be having the problem because to solve many of my dependency conflicts I created a module-info.java file for my project.  I don't actually need to treat it as a module, except that the side effects of using "requires" within the module-info file solve those conflicts, and I can't otherwise solve the problem that, for example, GWT and Ant both define a BuildException class (among other myriad name conflicts).  But again... that problem can be at least sometimes solved by breaking the code up where conflicts occur (which again is off the time to due time/effort/budget conflicts).  Moving all of the GWT code to one project, or to three (client/shared/server), and the build code (Ant tasks) to another, and other code to other places, could help... 

An alternate option might be to rewrite the entire build process to use Maven or Gradle (many other, newer, smaller projects here use Gradle), but again... that's a massive detour that I'll take if I must, but it seems possible that this upgrade effort will wind up getting shelved before I have time to do that.

SMALL ASK: Could GWT rename its BuildException class to GwtBuildException, to better support the twilight world of leaving Java 8 without entirely moving to modules?

Anyway, thanks for all the helpful input.  The main points of "don't use jakarta yet", "abandon embedded Jetty", and "refactor your disastrously monolithic kaiju into something realistic" all help.

That said... I'd still like to at least have a better understanding as to why I get "Error occurred during initialization of boot layer", "java.lang.module.FindException: Module gwt.user not found, required by com.xxxxx.myapp" when the GWT container is in the class path, as well as if I explicitly add the gwt-user.jar to the path in the Run Configuration or into WEB-INF/lib (like get-servlet.jar).

Colin Alworth

unread,
Jun 12, 2024, 12:14:48 PMJun 12
to GWT Users
> Clearly the GWT plugin/installed Jetty are not Jakarta-ready.  I could try to update and rebuild the plugin to make it so (maybe), but I'm so overwhelmed with other chores that I can't afford having that turn into another rabbit hole.  It's easier/safer/wiser to go back to javax.
If you mean the dev mode app server, there is no plan to do that _in gwt itself_, but there is an extension point in GWT that would let you do it yourself. Someone else has been thinking about building a small ecosystem around this in the issue tracker, but I haven't seen any movement here - see the discussion at https://github.com/gwtproject/gwt/pull/9866. We could easily have a jetty-12 impl, letting you run either jakarta or javax servlets, or switch to other servlet containers, and control as much or as little of the setup as you want.
If you mean a particular plugin that you use with GWT, there are so many possible plugins out there, we can't guess which one isn't working for you. Most should be able to let you run your own external server though, or specify your own server using the -server argument (and implement it yourself, as linked/discussed above).

> MEDIUM ASK: Can anyone point me to better documentation or a tutorial or a how-I-did-it-blog post on getting that set up?  Like I said, I can figure it out, I'm sure, but I'd rather do it the quick/easy/no-wasted-time way.
If using maven, check out the modular-webapp archetype for a very light example, at https://github.com/tbroyer/gwt-maven-archetypes/. If not, please give us more detail about what you are using (or intend to use).

> SMALL ASK: Could GWT rename its BuildException class to GwtBuildException, to better support the twilight world of leaving Java 8 without entirely moving to modules?
GWT doesn't have a BuildException class - can you give the fully qualified class name of the type that is irritating you? I see that Ant has such a class, and Gradle too, might you be thinking of one of those?

Bob Lacatena

unread,
Jun 14, 2024, 10:53:52 AM (12 days ago) Jun 14
to GWT Users
@Colin, thanks for getting back to me on this.  I couldn't reply right away because my wife was getting cataract surgery; it's not that this wasn't important.

> If you mean a particular plugin that you use with GWT...
I'm using the Eclipse GWT 4.0.0 plugin you guys recently completed (using the updated build, to fix the "support Eclipse 2024-03" issue; thanks for that).  I think in your lingo I therefore mean the dev mode app server.  I might look into that myself to get jetty-12 implemented, but for now I've abandoned jumping to jakarta as "a bridge too far" and am trying to solve my issues another way (likely by grumbling, rolling up my sleeves, and refactoring the mess the way it should have been done to start with, and the way I would have demanded had I worked here when it was first bungled).

> If using maven... [I'm not]... If not, please give us more detail about what you are using (or intend to use).
After further investigation, much of my issues around this seem to be that the. appropriate java command to run the web app (or Jetty itself) is not being assembled correctly by either Eclipse, the GWT plugin, or both.  There are various options that are needed and are not properly set.  That said, even if I do/can get that working, I don't think that's the right approach.  As you're going to deprecate the embedded Jetty server, I should do whatever is needed there to run my own external server(s).  That's what's unclear to me.  There are ancient references to it in the documentation at gwt.project.org, but I'm unclear on what is really needed.  Do I need to set up and run a code server with my own Jetty or Tomcat local installation?  If so, how is that set up?  Or do I need to run my own app server (again, either Jetty or Tomcat).  The web app setup is obvious (I think... or are there special runtime parameters to direct it to the proper code server port?).  Forgive my ignorance on this, but if this is the path forward for GWT in general, I'd really like to see some clear documentation on how to set this up or at least what it is going to look like (in general, no specifics, obviously it should involve thinking and work on my part). Last note: I am assuming the code server will be easier to get working with Java 17 modules because it will (in my case) have less jar dependencies, as it only needs them for shared and client code.  That said... I might need to run both externally to get it all sorted out.  Again, my own thinking on this isn't that clear because I'm not in the weeds enough on what the plugin is really doing and how things work under the hood.

To give a shorter, more direct answer: I want to develop code in Eclipse in Java 17, and be able to run the code server and web app any way possible, so that GWT code compiles/recompiles as needed, and the web app can be accessed in the browser, and I can do iterative test-code-test-code development on a daily basis.

> GWT doesn't have a BuildException class
This was my bad.  When I got the conflict I assumed it was something in gwt-dev.jar related to GWT, but upon further investigation (unpacking the jar), I see that the conflict is caused because the ant BuildException.class file is embedded in the get-dev.jar (and possibly because the package/path is com/google/gwt/thirdparty/apache/ant/BuildException.class rather than Ant's org/apache/tools/ant/BuildException.class.  A recurring problem in upgrading to Java 17 comes from class name/version exceptions that are now verboten.  My current solution of getting Ant out of this project will have to do (as it's better architecture anyway, and should have been done by my predecessors on day 1, i.e., don't bundle custom Java ant tasks with the application code).

Jens

unread,
Jun 17, 2024, 12:17:26 PM (9 days ago) Jun 17
to GWT Users
> If using maven... [I'm not]... If not, please give us more detail about what you are using (or intend to use).
After further investigation, much of my issues around this seem to be that the. appropriate java command to run the web app (or Jetty itself) is not being assembled correctly by either Eclipse, the GWT plugin, or both.  There are various options that are needed and are not properly set.  That said, even if I do/can get that working, I don't think that's the right approach.  As you're going to deprecate the embedded Jetty server, I should do whatever is needed there to run my own external server(s).  That's what's unclear to me.  There are ancient references to it in the documentation at gwt.project.org, but I'm unclear on what is really needed.  Do I need to set up and run a code server with my own Jetty or Tomcat local installation?  If so, how is that set up?  Or do I need to run my own app server (again, either Jetty or Tomcat).  The web app setup is obvious (I think... or are there special runtime parameters to direct it to the proper code server port?).  Forgive my ignorance on this, but if this is the path forward for GWT in general, I'd really like to see some clear documentation on how to set this up or at least what it is going to look like (in general, no specifics, obviously it should involve thinking and work on my part). Last note: I am assuming the code server will be easier to get working with Java 17 modules because it will (in my case) have less jar dependencies, as it only needs them for shared and client code.  That said... I might need to run both externally to get it all sorted out.  Again, my own thinking on this isn't that clear because I'm not in the weeds enough on what the plugin is really doing and how things work under the hood.

To give a shorter, more direct answer: I want to develop code in Eclipse in Java 17, and be able to run the code server and web app any way possible, so that GWT code compiles/recompiles as needed, and the web app can be accessed in the browser, and I can do iterative test-code-test-code development on a daily basis.

Traditionally GWT SDK only had the class com.google.gwt.dev.DevMode. It is responsible to launch classic dev mode (the one that does require an obsolete browser plugin) or SuperDevMode together with an embedded servlet container, by default Jetty. SuperDevMode is implemented in class com.google.gwt.dev.codeserver.CodeServer and DevMode basically calls this class if you request it to launch SuperDevMode (which is the default behavior). Class DevMode has a parameter "-noserver" which skips starting Jetty and assumes you have your own server and deployment running. Because we advocate running your own servlet container, e.g. Jetty/Tomcat/..., it is enough to just launch CodeServer yourself. However you could also continue to use class DevMode and replace the embedded Jetty with your own implementation using DevMode -server your.impl.of.ServletContainerLauncher. Your own implementation could then be based on Jetty 12 for example (and possibly jakarta)

Personally I use Gradle and have a task that just launches CodeServer by executing a command line. I am pretty sure you could also write a similar ANT task using your current ANT setup. The command line looks like 

com.google.gwt.dev.codeserver.CodeServer -sourceLevel 11 -strict -failOnError - bindAddress 0.0.0.0 -port 9876 -style PRETTY -XmethodNameDisplayMode ABBREVIATED -workDir /client-project/build/gwt/work -launcherDir /client-project/build/gwt/war -src /shared-project/src/main/java -src /shared-project/src/main/resources com.example.MyGwtModule

The classpath should contain gwt-user/gwt-dev/gwt-codeserver, all compile-time dependencies you need for GWT compilation as well as classes + sources + resources related to your GWT UI and DTOs. You would need to use ANT fileset/dirset/files to include/exclude only the files of your single project that are relevant for GWT compilation. Once you have that set of files figured out you can run GWT CodeServer in isolation via ANT with its own GWT focused classpath and you should not have any trouble with other dependencies that you need on the server only.

Once you have that running, you need to decide how you want to run a servlet container. Personaly I use Docker + docker-compose + Jetty image + shell script.

 

Craig Mitchell

unread,
Jun 17, 2024, 10:09:58 PM (9 days ago) Jun 17
to GWT Users
It's when you see crazy long command lines like that, you start to appreaciate Maven (or Gradle).  The same command in Maven is "mvn gwt:codeserver -pl *-client" (yes, I know you see still need to setup the launcherDir, warDir, etc in the pom.xml files, but that seems much easier than one huge command line).
Reply all
Reply to author
Forward
0 new messages