cporter71
cporter71

Reputation: 41

How can I create executable jars with embedded tomcat 9?

Has anyone tried the plugin to build an executable war/jar using Tomcat 9?

I attempted to do so however ran into:

Exception in thread "main" java.lang.NoSuchMethodError: org.apache.catalina.startup.Catalina.setConfig(Ljava/lang/String;)V
  at org.apache.tomcat.maven.runner.Tomcat7Runner.run(Tomcat7Runner.java:240)
  at org.apache.tomcat.maven.runner.Tomcat7RunnerCli.main(Tomcat7RunnerCli.java:204)

I looked at the source and changed Catalina.setConfig() to Catalina.setConfigFile() based on docs here. After doing so the .extract dir is just empty:

use extractDirectory:.extract populateWebAppWarPerContext warValue:ROOT.war|ROOT populateWebAppWarPerContext contextValue/warFileName:ROOT/ROOT.war webappWarPerContext entry key/value: ROOT/ROOT.war expand to file:.extract/webapps/ROOT.war Exception in thread "main" java.lang.Exception: FATAL: impossible to create directories:.extract/webapps at org.apache.tomcat.maven.runner.Tomcat7Runner.extract(Tomcat7Runner.java:586) at org.apache.tomcat.maven.runner.Tomcat7Runner.run(Tomcat7Runner.java:204) at org.apache.tomcat.maven.runner.Tomcat7RunnerCli.main(Tomcat7RunnerCli.java:204)

.... although there is a ROOT.war, server.xml, web.xml in the *-exec-war.jar.

Is there a better way to be creating exec-jars with embedded tomcat 9?

Upvotes: 3

Views: 1311

Answers (2)

rafaelnaskar
rafaelnaskar

Reputation: 783

For future searchs, one solution is to use the DirResourceSet or JarResourceSet.

    String webAppMount = "/WEB-INF/classes";
    WebResourceSet webResourceSet;
    if (!isJar()) {
        webResourceSet = new DirResourceSet(webResourceRoot, webAppMount, getResourceFromFs(), "/");
    } else {
        webResourceSet = new JarResourceSet(webResourceRoot, webAppMount, getResourceFromJarFile(), "/");
    }
    webResourceRoot.addJarResources(webResourceSet);
    context.setResources(webResourceRoot);


public static boolean isJar() {
    URL resource = Main.class.getResource("/");
    return resource == null;
}

public static String getResourceFromJarFile() {
    File jarFile = new File(System.getProperty("java.class.path"));
    return jarFile.getAbsolutePath();
}

public static String getResourceFromFs() {
    URL resource = Main.class.getResource("/");
    return resource.getFile();
}

When add the webapp, use root path "/" for docBase:

tomcat.addWebapp("", "/")

Credits for: https://nkonev.name/post/101

Upvotes: 0

cporter71
cporter71

Reputation: 41

For those looking for a solution it was fairly straight forward to checkout the code for the plugin and make a few changes to get this to work. Namely: Update POM to change the depends to Tomcat 9 Fix compile errors which generally stem from deprecated methods. The lookup on these methods can be found here. For example:

-                container.setConfig( serverXml.getAbsolutePath() );
+                container.setConfigFile( serverXml.getAbsolutePath() );

... and ...

-            staticContext.addServletMapping( "/", "staticContent" );
+            staticContext.addServletMappingDecoded( "/", "staticContent" );

There are a few others but generally not difficult to resolve. After doing so I updated my app's pom to use the modified version and was able to generate a Tomcat 9 exec jar.

I would love to hear what others are doing here. I know some are programmatically initializing Tomcat via a new Tomcat() instance however curious what other solutions exist ready made. Thanks

Upvotes: 1

Related Questions