-
Notifications
You must be signed in to change notification settings - Fork 382
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Build GWT against Jetty transitive dependencies baseline #9720
Comments
Having studied the structure of GWT source code, I realized that "gwt-dev" and its siblings are Maven builds and use fixed versions for the common artifacts. I wonder, if we could change that and inherit the common artifacts from "Jetty" transitive dependencies set instead, expecting that GWT would still build and run. In fact, at I changed to Can anyone help? |
You can not downgrade ASM to 5.0.1 because GWT compiler in gwt-dev.jar needs ASM 7.1 to support Java 11. The only option is upgrading Jetty to a compatible version or not using DevMode with embedded Jetty. Use CodeServer with your own server instead, which is the recommend way to use GWT these days. |
I understand but I cannot afford not using DevMode. Can't we build GWT against a version of Jetty based on same version of asm? This would keep everyone happy 😊 see also gwtproject/tools#21 |
Could very well be that you can not use future GWT versions then. At least future GWT based on J2CL will not have a DevMode with embedded Jetty for server code.
Sure, if a decision is made to drop Java 7 support because the Jetty version in question requires Java 8. Currently we still compile to Java 7 byte code for those enterprise users so that server side jars, e.g. gwt-servlet.jar, can run with legacy Java 7. |
Fwiw: https://groups.google.com/g/google-web-toolkit-contributors/c/tMR3Dv1YBBE (almost two years old) I think nobody objects to dropping Java 7 support. |
Thank you @jnehlmeier and @tbroyer.
Indeed, I am stuck at GWT 2.8.2
I am looking forward to that.
I agree, Java 7 could be dropped and this should make room for classpath alignment between GWT and Jetty so that DevMode can be used with GWT 2.9.0+, until J2CL replaces DevMode. |
Yeah I know. Personally I am fine with dropping Java 7. However the question is if we want to invest work into upgrading Jetty again or rather remove jetty from DevMode. We also have to find a solution to support So I am thinking a bit more long term, given the limited maintenance effort for GWT these days. I could even imaging @eliasbalasis asking for Jetty 11 in a couple of months because he wants to use newer libraries that require jakarta now ;-) And then we might be in ASM trouble again, if jetty becomes too new. That is why I strongly think we should:
|
I've been advocating this for years, so you're preaching to the choir here as far as I'm concerned.
This should be relatively easy, possibly with a bit of refactoring around I'd say this is low priority, and could be done as a third-party (possibly with a bit more copy/pasting than if it was "built in"). |
Well said @jnehlmeier and @tbroyer, I agree that until DevMode gets permanently removed there could still be a possibility of having to make further adjustments to support newer versions of Jetty. I can promise you I will not request this.
Until then, can we at least drop Java 7 and use a compatible version of Jetty one depending on same version of ASM? with or without "Jakarta namespace" (your call). |
@tbroyer I know you have. I have created https://groups.google.com/g/google-web-toolkit-contributors/c/iU9hckIab2o and hope we can get to a decision. I hate it that it feels like nobody is really responsible for such decisions.
Of course it can be retired. A lot of people are not using it anymore, or at least are not using the embedded Jetty anymore without loosing productivity. These people are using Maven / Gradle and use Maven / Gradle plugins to launch GWT CodeServer and a servlet container of choice. Or they use a ready made Docker image that contains a preconfigured servlet container to deploy the app, usable by all employees in a company. Or they simply use their IDE to launch Jetty / Tomcat (works well with IntelliJ for example). So there are quite a few options that don't really hurt productivity. With J2CL you have to launch your server side code yourself anyways. |
I am not perfectly familiar with J2CL but since it still needs a code server it won't change the situation much. I have to admit that this last bit has started making me lean towards retirement of DevMode even though it doesn't suit my team's needs. I equally consider support for Jakarta namespaces low-priority. @jnehlmeier Finally, it shouldn't be too difficult to drop Java 7 and use a compatible version of Jetty, one depending on same version of ASM. This should keep everyone happy 😊 |
A workaround has been found. (see #9693 )
|
You wouldn't by any chance have an example of how to set this up? The ability to do this seems to always be slightly outside of my grasp, being mostly a coder and not having much knowledge about servlet containers or similar. I've successfully managed to run tomcat and having deployed a war:exploded of a web-module, so I know tomcat itself is working, but naturally this does not provide a CodeServer and hence debugging abilities. I would think that it should be as simple as making my GWT run config start with "-nostartServer -war <some.smart.dir>" and then pointing a tomcat run config to that somehow, but I have simply not been able to connect these two sides in a functional setup. Sorry for bringing this up on this bug report. |
I use IntelliJ Ultimate, which allows you to configure applications servers within the IDE. You would download/install Jetty locally, configure that installation within IntelliJ as application server and then create a run configuration for Jetty. Within the run configuration you can tell IntelliJ which artifacts to deploy. These artifacts can either be produced by IntelliJ itself or you use external artifacts (e.g. produced by Maven/Gradle). As I use Gradle I configured the *.war file produced by Gradle as external artifact. In addition I configured the Jetty run configuration to launch the Gradle build before starting Jetty itself. So whenever I restart Jetty within IntelliJ, Gradle will be launched beforehand and will rebuild the war. GWT CodeServer / DevMode is started separately in a terminal window (either within IntelliJ or external) using a custom Gradle task which basically just forks a JVM and launches CodeServer main class with the appropriate classpath and parameters. Given that CodeServer or DevMode are just Java classes you can launch them however you want. And yes you would need to make sure that the output of either If you use IntelliJ's own artifact building feature then you can add any additional directory to an artifact (project structure -> artifacts -> select your artifact -> the small + button allows you do add various content). So you could add the directory you have used with |
@jnehlmeier
This was more or less what I had done before, only with tomcat. I've since tried it with jetty as well, and they seem to work more or less the same for me.
This seems to be the missing piece of the puzzle. I was still not seeing anything different, but now the good old dev mode bookmarklet did its thing, and sourcemaps and debugging with this now seems to work! This whole thing is quite cumbersome though, compared to the more or less one step to do all this with the built-in jetty. I'm sure there's something I could set up to trigger the recompile automatically without the bookmarklet, but there's still a large amount of extra compiling necessary. The building of the artifact for the tomcat run configuration builds 3 permutations, and then the one that will actually be used is compiled again when hitting the bookmarklet, if I understand how this works. This is simply because of 3 locales, which have been constrained to 1 by the superdevmode propertym which is not active when building the artifact. Have been looking into how to bypass this, with the inheriting module that overwrites the locale property, but so far I have not found a way to dynamically choose which module is the one to run, without having a whole separate web.xml or similar. Maybe I'll fix that in time. |
If you don't use an ancient version of GWT then you usually don't need these bookmarklets. If setup correctly, then GWT recompiles the app automatically when you reload the browser and changes have been detected.
Because your IntelliJ artifact has "GWT compile output" configured in the war. This tells IntelliJ to run a GWT build as configured in the GWT facet of your project. For development you don't need that so just remove it from the artifact (or create a second "dev" artifact and deploy that one). For development you only need the CodeServer/DevMode output in your war.
Thats the single permutation produced by CodeServer / DevMode matching your browser. As said above, with more recent GWT versions you usually don't need that bookmarklet as long as you make sure that the output of CodeServer/DevMode -launcherDir/war is inside your war. Maybe because you have "GWT compile output" in your artifact, it overrides the special code produced by CodeServer/DevMode -launcherDir/war which defeats the "auto recompile on reload" feature. Or you first build your artifact and then launch CodeServer/DevMode. In that case the special files produced by CodeServer/DevMode might not end up in your deployed war file. |
@jnehlmeier Thank you so much for all the help! |
I have a patch in progress that updates latest HtmlUnit, and as part of this, jetty must be updated. I switched to latest jetty, 9.4.43.v20210629, and only found there to be a few things that had to be updated inside of GWT:
To build this, use https://github.com/niloc132/gwt/tree/htmlunit-upgrade for your gwt/ code, and https://github.com/Vertispan/tools/tree/update-htmlunit for your tools/ directory, so that the new dependencies are available. There are two bugs in htmlunit that have been reported that we will need to have fixed before this can ship, as several tests break in gwt-user tests, but so far, it seems to function properly. To try using it from maven, please point to https://repo.vertispan.com/gwt-snapshot/ and use version 2.10.0-htmlunit-upgrade-SNAPSHOT. |
Thanks @niloc132.
|
@sstamm can you give some detail on how you got that error? How you're running dev mode, what else is running in your server or on your classpath, etc. The class is definitely on the classpath somewhere, since
Assuming you are using the very latest on my branch (which I think is slightly ahead of the maven artifact I deployed), line 450 is the super call here:
which suggests that super wasnt able to find it either, even though that is what would have been called without our subclass. I'm making a new build shortly to tweak a few other small things and update it to latest upstream, can you confirm that the bug still happens and see if you can add any extra detail? I'll add an edit here when the snapshot is updated. EDIT: updated at https://repo.vertispan.com/gwt-snapshot/com/google/gwt/gwt-dev/2.10.0-htmlunit-upgrade-SNAPSHOT/, see version 20211001.151235-5 etc. |
@niloc132 I'm runnig devmode out of Eclipse (GWT Eclipse Plugin 3.0.0). I debugged into it:
systemClassLoader does contain the class, but WebAppContextWithReload.this.isSystemClass(name) retuns false So finally WebAppContextWithReload.this.isServerClass(name) causes the Exception. |
How are you reproducing this, so I can see it also and work on it? For example, is this a normal startup of a plain application with no servlets (or one simple servlet etc), or does this require some specifics from your own application to cause this? The class you seem to be trying to look up is part of jetty itself, and it looks like some jetty xml file is being read - do you have some extra jetty xml files in your project that aren't part of GWT itself? There is a special check to allow some startup code to be able to get outside the server classloader, but it isn't being triggered here. I see two paths that this could take to fix it (either "we need to preload the class so that these xml files work, before we replace the classloader", or "Jetty's WebAppClassLoader can no longer be extended in the way we do it, we need to delegate to specific superclass methods, since |
@niloc132 dang it, this was the right hint, thanks! Do you know what I've to use instead of WebAppContext?
|
This is the correct way to do it: https://www.eclipse.org/jetty/documentation/jetty-9/index.html#jetty-env-xml But it looks like the filtering in GWT's The right answer in your case anyway is to stop using DevMode's embedded server, and instead use a real Jetty (or Tomcat or whatever) server, along with CodeServer (or DevMode's |
The filtering seems to be correct - that class is not legal to load from inside the application, but jetty's WebAppClassLoader is intended to be able to load it within the context of the
Within that scope, the WebAppClassLoader.__loadServerClasses threadlocal is set to true, and loadClass is supposed to succeed... except GWT's subclass passed a "bootstrapOnlyClassLoader", so WebAppClassLoader can't find its own classes properly, and the threadlocal isn't visible, else we could use it to read from the My guess is that Jetty is "expecting" that GWT overrides loadClass instead of findClass, as the contract for ClassLoader.loadClass is that loadClass is called first, and only if that fails (going up the classloaders until there is no parent) does findClass get called. WebAppClassLoader.findClass has transformer logic as noted, but loadClass is where WebAppClassLoader does the check if it should permit the class to be loaded in this special case due to being in the lambda above. |
As a developer coming from a Jakarta background (to which I naturally evolved, coming previously from Java EE and having never been much convinced by the Spring alternative), and currently considering GWT for building GUIs, I’d view it as an important point that GWT would adopt the Jakarta namespace. I wouldn’t want to come back to JPA 2, and so on, now that I have switched my dependencies to JPA 3 (and similarly for many other Jakarta specs) and have published code that refers to the new namespace. Not that it would be extremely hard work, admittedly, but it would be going in the wrong direction.
Well, Spring is essentially an alternative, or even a competitor, to Jakarta EE (and was an alternative / a competitor to Java EE previously), so I wouldn’t consider this point as a strong indication. You might want to consider the behavior of other actors of the Java ecosystem. Jetty has switched though maintains compatibility (v11 is Jakarta, v10 uses Java EE namespace); Eclipse (obviously) has switched; IntelliJ seems to support it (I just did a quick check); Hibernate seems to have switched to Jakarta being supported first; and so on. Basically is seems like the major actors are deciding to switch to Jakarta while maintaining compatibility with Java EE but gently pushing their users to upgrade to Jakarta. It would be strange that GWT would stick with the old namespace for still quite some time; it might feel like signalling non up-to-date technology. (I know that I am just one user among many, but I thought I’d let you know my feelings; it seems to me that I might well be a typical or growing case among your users. Sorry for the noise if this opinion is inappropriate here.) |
@oliviercailloux Please note that we are only talking about:
|
@sstamm I have just pushed a new build of the 2.10.0-htmlunit-upgrade-SNAPSHOT version to the same repo, can you try out your jetty use cases? From a quick local sample, I think I may have resolved that issue. |
Several old tests previously not able to run in HtmlUnit are now enabled, and two tests are disabled, linked to the appropriate bug report. The jaspi security/authentication module has been disabled in the dev mode server. It is no longer included in the base jetty install due to licensing reasons, and is disabled by default here for the same reason. Many small changes were necessary across various parts of testing and dev mode infrastructure: * HtmlUnit has introduced a proxy for window and document, legacy dev mode needs to treat those objects as if they were the real instance. * HtmlUnit has additional protection to avoid letting a page interact with a real Java object. This had to be relaxed in order to let legacy dev mode tests continue to work. * The custom classloader used to run a webapp within dev mode now overrides loadClass instead of findClass, to correctly delegate to Jetty's own implementation to handle startup issues. Additionally, isSystemClass and isServerClass are relocated and deprecated. Bug: #9720 Bug-Link: gwtproject/gwt#9720 Co-Authored-By: Mihai Stanciu <[email protected]> Change-Id: Ie14cb33cb0edea57c121de943f2964a8cf0540ee
GWT 2.10 will be released in the next few days, marking this as closed. |
GWT version: 2.9.0
Browser (with version): any
Operating System: any
Description
Running DevMode under GWT 2.9.x is practically impossible due to the build classpath inconsistencies.
see #9606 #9693
To permanently make the DevMode runtime classpath pains go away,
GWT needs to start getting built against the transitive dependencies baseline of the associated Jetty version.
Perhaps GWT built could start using "Ivy" for dependencies resolution, similar to Maven in order to achieve alignment with Jetty transitive dependencies baseline and produce a stable classpath at last.
Steps to reproduce
see my comments on #9606 and #9693
see also (gwtproject/tools#21)
Known workarounds
Maven classpath manipulation, as described in #9606 but doesn't work for GWT 2.9.0 due to its inconsistent build classpath.
More precisely,
gwt-dev
is built againstorg.ow2.asm:7.1
while the asociated Jetty is built againstorg.ow2.asm:5.0.1
This causes "Super DevMode" with either "GWT Eclipse Plugin" or Maven commands and
org.codehaus.mojo:gwt-maven-plugin
to crash with runtime classpath errors.A more recent version of Jetty is required as suggested under (gwtproject/tools#21) but even that won't permanently protect the build classpath from further abuse.
Besides,
org.ow2.asm
may not be the only misaligned transitive dependency.Links to further discussions
#9606
#9693
(gwtproject/tools#21)
The text was updated successfully, but these errors were encountered: