Problem running from Gradle

We recently switched to Gradle. Our stack is Vaadin 23, embedded Jetty, and Guice. When we run our main method through IntelliJ, everything works as expected. However, we want to run it from Gradle, which we set up. It works perfect on macOS and Ubuntu, but not on Windows.

Here is our Gradle task (simplified):

create<JavaExec>("startWebapp") {

    group = "mycompany"
    classpath = sourceSets.named("main").get().runtimeClasspath
    workingDir = project.projectDir

We get the following exception on startup:


I did some digging. It seems that, when running through Gradle, the classSet of LookupServletContainerInitializer#process is empty. What I have tried:

  • Compared the classpaths when running from IntelliJ to Gradle. They are the same. Only difference is that Gradle creates a temporary JAR with a manifest file, so any non-jar folders, such as src/main/java is prefixed with file://.
  • I think Gradle uses its own classloader, so I manually set the classloader in Jetty.
  • I tried to make a minimal, reproducible example, but could not reproduce the issue.
  • I tried manually adding the missing classes to classSet. The app then starts up, but is unusable. E.g., the app is just plaintext.


No help: I would suggest to go back to maven :grimacing:

I recall to have seen a similar issue with gradle fatJar because the META-INF/services entries got replaced instead of being concatenated. So the META-INF/services/jakarta.servlet.ServletContainerInitializer provided by Flow (and containg the reference to com.vaadin.flow.server.startup.LookupServletContainerInitializer) was suppressed by anoter file

@versatile-zorse That’s an interesting thought, but I have my own javax.servlet.ServletContainerInitializer in META-INF/services because previously had added some. Right now, though, it’s contents are identical to

@quirky-zebra Not an option. Company is switching to Gradle. Honestly, I was hesitant at first, but Gradle actually makes a lot more sense.