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

Add support for running with Undertow #431

Open
earldouglas opened this issue Feb 15, 2021 · 9 comments
Open

Add support for running with Undertow #431

earldouglas opened this issue Feb 15, 2021 · 9 comments
Assignees
Milestone

Comments

@earldouglas
Copy link
Owner

https://undertow.io/undertow-docs/undertow-docs-2.0.0/#creating-a-servlet-deployment

@earldouglas earldouglas self-assigned this Feb 15, 2021
@AugustNagro
Copy link

I'm trying to build a Spring Boot WAR for JBoss via the ContainerPlugin, without luck.

Is it not working because xsbt-web-plugin doesn't support Undertow yet? It looks like tomcat-embed-*.jar is added to the manifest regardless of what I put in Container / containerLibs.

@earldouglas
Copy link
Owner Author

Thanks for the info; that helps point me in the right direction. I will put something together for this later today.

@earldouglas
Copy link
Owner Author

Can you give TomcatPlugin a try, rather than ContainerPlugin? I can get a minimal Spring Boot project working with it:

  1. Follow steps (1) and (2) on the Spring Quickstart Guide

    Step 1: Start a new Spring Boot project
    Step 2: Add your code

  2. Add project/plugins.sbt
    addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "4.2.2")
  3. Port the given mvn.xml to build.sbt and enable TomcatPlugin
    libraryDependencies ++=
      Seq(
        "org.springframework.boot" % "spring-boot-starter-web" % "2.5.1",
        "org.springframework.boot" % "spring-boot-starter-tomcat" % "2.5.1" % "provided",
        "org.springframework.boot" % "spring-boot-starter-test" % "2.5.1" % "test",
      )
    enablePlugins(TomcatPlugin)
  4. Run it
    $ sbt
    > tomcat:start
    
  5. Test it
    $ curl localhost:8080/hello
    Hello World!
    

@AugustNagro
Copy link

Wow, thanks for the fast reply!

I followed your steps and created a minimal reproducer here: https://github.com/AugustNagro/springboot-mvp

Running with run works, but Tomcat / start does not. The log is:

INFO: Initializing ProtocolHandler ["http-nio-8080"]
Jun 20, 2021 7:24:40 PM org.apache.catalina.core.StandardService startInternal
INFO: Starting service [Tomcat]
Jun 20, 2021 7:24:40 PM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet engine: [Apache Tomcat/9.0.38]
Jun 20, 2021 7:24:40 PM org.apache.catalina.startup.ContextConfig getDefaultWebXmlFragment
INFO: No global web.xml found
Jun 20, 2021 7:24:42 PM org.apache.jasper.servlet.TldScanner scanJars
INFO: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
Jun 20, 2021 7:24:42 PM org.apache.catalina.core.ApplicationContext log
INFO: 1 Spring WebApplicationInitializers detected on classpath
Jun 20, 2021 7:24:42 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-nio-8080"]

@earldouglas
Copy link
Owner Author

I don't know much about Spring Boot, but based on the example project from https://start.spring.io/, I think you need to add one additional class:

src/main/scala/com/example/mvp/ServletInitializer.scala:

package com.example.mvp

import org.springframework.boot.builder.SpringApplicationBuilder
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer

class ServletInitializer extends SpringBootServletInitializer:

  override def configure(application: SpringApplicationBuilder): SpringApplicationBuilder =
    application.sources(classOf[SpringMVP])

Then run tomcat:start, and you should see a bunch of Spring-related output, as well as a working endpoint:

$ curl localhost:8080
Gus

@AugustNagro
Copy link

Awesome, tomcat:start is working!

But when running on JBoss, I get

java.lang.ClassCastException: org.apache.tomcat.websocket.server.WsServerContainer cannot be cast to io.undertow.websockets.jsr.ServerWebSocketContainer​

I've tried excluding the Tomcat WS dependency as per stack overflow, but no dice so far.

    excludeDependencies ++= Seq(
      // https://stackoverflow.com/questions/25792121/spring-boot-websockets-in-wildfly?answertab=votes#tab-top
      "org.apache.tomcat.embed" % "tomcat-embed-websocket"
    )

@AugustNagro
Copy link

Ok, got it working in JBoss!

Just switched to the ContainerPlugin.

@earldouglas
Copy link
Owner Author

It looks like spring-boot-starter-web is pulling in spring-boot-starter-tomcat as a transitive dependency, which conflicts with JBoss's own libraries. You can exclude it from being included by adding an exclude() to the libraryDependencies line:

libraryDependencies ++= Seq(
  "org.springframework.boot" % "spring-boot-starter-web" % SpringBootVersion exclude("org.springframework.boot", "spring-boot-starter-tomcat"),

Just switched to the ContainerPlugin.

Note that this has no effect on the .war file produced by package, and will prevent you from being able to launch Tomcat via tomcat:start.

@AugustNagro
Copy link

Sweet, that's a better solution.

@earldouglas earldouglas removed their assignment Jul 11, 2021
@earldouglas earldouglas self-assigned this May 22, 2022
@earldouglas earldouglas added this to the v5 milestone Aug 5, 2023
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

2 participants