Skip to content
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

Super dev mode fails with jetty-web.xml #9809

Open
cvoegtle opened this issue Mar 20, 2023 · 9 comments
Open

Super dev mode fails with jetty-web.xml #9809

cvoegtle opened this issue Mar 20, 2023 · 9 comments

Comments

@cvoegtle
Copy link

GWT version: 2.10.0
Browser (with version): Chrome 111.0.5563.65
Operating System: Windows 10


Description

since GWT 2.10.0 the embedded jetty fails to start properly in super dev mode, if the web application is configured with a jetty-web.xml. We use the jetty-web.xml to configure a security Handler for basic authentication.
Regarding the Jetty 9.4 documentation the class org.eclipse.jetty.webapp.WebAppContext is the class to configure in jetty-web.xml.
With GWT 2.10.0 the jetty-web.xml processing fails with the following exception:

java.lang.ClassNotFoundException: org.eclipse.jetty.webapp.WebAppContext
	at java.lang.ClassLoader.findClass(ClassLoader.java:523)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
	at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:487)
	at com.google.gwt.dev.shell.jetty.JettyLauncher$WebAppContextWithReload$WebAppClassLoaderExtension.loadClass(JettyLauncher.java:458)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
	at org.eclipse.jetty.util.Loader.loadClass(Loader.java:64)
	at org.eclipse.jetty.xml.XmlConfiguration$JettyXmlConfiguration.nodeClass(XmlConfiguration.java:477)
	at org.eclipse.jetty.xml.XmlConfiguration$JettyXmlConfiguration.configure(XmlConfiguration.java:417)
	at org.eclipse.jetty.xml.XmlConfiguration.configure(XmlConfiguration.java:364)
	at org.eclipse.jetty.webapp.JettyWebXmlConfiguration.lambda$configure$0(JettyWebXmlConfiguration.java:94)
	at org.eclipse.jetty.webapp.WebAppClassLoader.runWithServerClassAccess(WebAppClassLoader.java:138)
	at org.eclipse.jetty.webapp.JettyWebXmlConfiguration.configure(JettyWebXmlConfiguration.java:92)
	at org.eclipse.jetty.webapp.WebAppContext.configure(WebAppContext.java:498)
	at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1409)
	at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:910)
	at org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:288)
	at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:524)
	at com.google.gwt.dev.shell.jetty.JettyLauncher$WebAppContextWithReload.doStart(JettyLauncher.java:568)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:73)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:169)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:110)
	at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:97)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:73)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:169)
	at org.eclipse.jetty.server.Server.start(Server.java:423)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:110)
	at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:97)
	at org.eclipse.jetty.server.Server.doStart(Server.java:387)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:73)
	at com.google.gwt.dev.shell.jetty.JettyLauncher.start(JettyLauncher.java:776)
	at com.google.gwt.dev.DevMode.doStartUpServer(DevMode.java:636)
	at com.google.gwt.dev.DevModeBase.startUp(DevModeBase.java:898)
	at com.google.gwt.dev.DevModeBase.run(DevModeBase.java:705)
	at com.google.gwt.dev.DevMode.main(DevMode.java:432)

Steps to reproduce

import this demo project into IntelliJ IDEA. Excecute the run configuration named Demo. That will output the exception above on the console.

Proof that the configuration is correct in general:
a) downgrade to GWT 2.9.0. That will work instantly
b) build a war file with mvn clean install and deploy it to a Jetty 9.4. That will work, if you place the realm.properties outside the WAR-file.

Known workarounds
Links to further discussions
@niloc132
Copy link
Contributor

This looks like the issue that was reported while this update was in development, at #9720 (comment). The example xml file is decently close to yours too #9720 (comment). Testing seemed to suggest that this case was resolved with no other follow-up from the user).

I'll take a look at this later this week, given some free time.

That said, we continue to discourage using the super dev mode's "built in" jetty for hosting any server code more complicated that "hello world" - we are limited in how that server can be updated and made more flexible (since dev mode itself needs it to be configured a certain way, with specific versions), so necessarily some projects will always find problems with any way it is set up. Instead:

  • keep server and client classpaths separate (with an optional "shared" or "common" project for classes both should use,
  • run your own server, as if you weren't debugging the client at all,
  • start super dev mode with the -launchDir or -war to tell it where to deploy modified JS files such that the server above knows about them, will tell the browser about them. This is the same idea as if you were writing JS by hand, or using any other existing JS build tools to generate JS to be hosted by your server.

@cvoegtle
Copy link
Author

I agree #9620 seems to be related. jetty-env.xml and jetty-web.xml are siblings and the stacktrace is also similar.

It would be great if you could come up with a solution or a workaround.

I will look into your advice to restructure our project. I understand the part about server and client, but I am unsure how to handle the shared classes. We use a command pattern with hundreds of commands and responses. It would be a pain to have them in a separate library.

Instead I would try to get rid of the jetty-web.xml

@jnehlmeier
Copy link
Member

but I am unsure how to handle the shared classes. We use a command pattern with hundreds of commands and responses. It would be a pain to have them in a separate library.

If you use Maven or Gradle you can setup a multi-module project with three modules: client, shared, server. Then you can let client and server module depend on the shared module and Maven/Gradle will take care of building.

For Maven you can use the modular-webapp archetype of https://github.com/tbroyer/gwt-maven-archetypes to create a demo project to see how it would look like.

The same can be achieved with Gradle either using any maintained GWT plugin for Gradle or by configuring Gradle by hand.

@cvoegtle
Copy link
Author

Thank you. The archetype is very helpful. Now I understand how the structure should look like. I have to see, if I can adapt it to our environment. We have our own testing framework for end-to-end-unit-tests in pure java. That will still require access to client, server and shared classes.

@niloc132
Copy link
Contributor

@cvoegtle in that case it could be worth splitting even the client code into "actually client-only code" for the gwt application itself, and "JVM-testable client code" - effectively shared code, and the test part of the project could depend on the server (via maven/gradle at least) to build up the classpath necessary. Or, another module for testing could be added.

@cvoegtle
Copy link
Author

I played a bit with the gwt-maven-archetypes. It was easy to start the application from the command line, but I still struggle with the run configurations in IntelliJ. That might be a solvable problem, but I am afraid to restructure our pom.xml with 1300 lines plus a couple of maven assembly descriptions. Getting rid of the jetty-web.xml would be easier to achive.

@mournblade
Copy link

Hello, I am having the same issue, but for a different reason, so I start by writing here. If anyone wants me to create a new ticket, I'm happy to do so.

I have a jetty-web.xml because I need to run my super dev mode with a context path, so that the URL becomes /myappname/start.jsp

<Configure class="org.eclipse.jetty.webapp.WebAppContext">
    <Set name="contextPath">/myapp</Set>
</Configure>

but, as mentioned I get the ClassNotFoundException.

It's not important to me to have the Jett-web.xml but I need to run SuperDevMode mode with a context path. Is there some other way?

@jnehlmeier
Copy link
Member

@mournblade GWT 2.11 has deprecated the use of embedded Jetty as application server to deploy your server side application. Instead use a local jetty installation, a jetty docker image or launch jetty via a maven/gradle plugin to deploy your *.war file or an exploded war folder. Then you can continue to use jetty-web.xml to define the context path or you rename the war file to myapp.war as jetty uses the war file name as context path by default (ROOT.war deploys to the root)

You would start GWT SuperDevMode then as

  • DevMode -noserver -war <path/to/exploded/war> or
  • CodeServer -launcherDir <path/to/exploded/war>

You have to make sure that the output of either command ends up in the war file because a special *.nocache.js file is generated for SuperDevMode.

@mournblade
Copy link

@jnehlmeier yeah, I've seen all the people being mad at embedded jetty. The "problem" is that I'm using intellij, and their GWT-plugin is great. You just click a button and it starts super dev mode - I am up and running instantly and can just reload the browser to see changes. Been doing this for 12+ years, the new stuff sound way more cumbersome. I guess I'll have to figure it out if it is removed, but it's too bad.

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

No branches or pull requests

4 participants