Issues with deploying a Spring Boot application onto JBoss
By: Conor Prunty
Tags: Spring Boot, Jboss, Java, Deployment

The prerequisite to reading this is you should have familiarity with Spring Boot, and how to deploy an application to JBoss in general.

Spring Boot configuration

To begin, there are some configurations that you may need so let’s dive in.

First things first; package up the application as a war file in the pom.xml like so: <packaging>war</packaging>

Next, if you use spring-boot-starter-web , you’ll likely have to exclude the embedded Tomcat:

<dependency>

< groupId>org.springframework.boot</groupId>

< artifactId>spring-boot-starter-web</artifactId>

<exclusions>

<exclusion>

<groupId>org.apache.tomcat.embed</groupId>

<artifactId>tomcat-embed-websocket</artifactId>

</exclusion>

</exclusions>

</dependency>

I then added a simple jboss-web.xml located in src/main/webapp/WEB-INF (I also had to create that folder structure starting with webapp) with the contents just being:

<?xml version="1.0" encoding="UTF-8"?>

<jboss-web>

<context-root>/yourRootPath</context-root>

</jboss-web>

And lastly, I then had to add a failOnMissingWebXml in the pom file, under a maven-war-plugin plugin:

<plugin>

<artifactId>maven-war-plugin</artifactId>

<version>2.4</version>

<configuration>

<failOnMissingWebXml>false</failOnMissingWebXml>

</configuration>

</plugin>

And voila, my application now deploys successfully to JBoss.

Locate your war file

There are two different ways of deploying on JBoss; standalone and domain.

So depending on which way you are deploying, the deployed file is in a different location.

Standalone

Standalone is the simple one, the deployed file is pretty much where you dropped it, i.e. <JBoss_Home>/standalone/deployments

However, if you deployed on standalone mode via the management console, then follow the steps for domain mode below, but replace domain.xml with standalone.xml .

Domain

With domain mode, you must deploy via the management console (or the jboss-cli, but much easier on the console). It will update your domain.xml , so locate something like the following section once deployed:

<deployments>

<deployment name="foo.war" runtime-name="foo.war">

<content sha1="d991471f79045413a7c63b8c2b5d4dc345be8808"/>

</deployment>

</deployments>

The important part here is the value after sha1; it specifies the subfolder location of the deployed file.

Break it up into two parts; the first two characters and then the rest. So the subfolder would look like:

d9/91471f79045413a7c63b8c2b5d4dc345be8808

And this is located at:

<JBoss_Home>/data/content/d9/91471f79045413a7c63b8c2b5d4dc345be8808

And in that location there will be a file named content

This content file is actually the war file!

So the easiest option is to copy it to a temporary location, rename as foo.war and then open it as normal with WinZip or 7Zip etc. And there you have your deployed file.

Endpoint issues

So at this point, you have a successfully deployed Spring Boot application on JBoss, so kudos! However, the fun never stops with technology, and you may have an issue accessing your endpoints.

In my case, everything deployed successfully, however, I couldn’t hit any endpoint. I just kept getting a HTTP 405 response. I thought the path I was using might be wrong, but if I entered a random path, I got an expected 404 response.

It took a while to find out that because of the node spring-boot-starter-web , it was including Tomcat by default under the hood, and nothing would work.

So the change to make in your project’s entry point is to extend SpringBootServletInitializer and to override the configure method:

public class MyApplication extends SpringBootServletInitializer { @Override

protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {

return application.sources(MyApplication.class);

} public static void main(String[] args) {

SpringApplication.run(MyApplication.class, args);

} }

And all endpoints were successful upon redeploy. Note that if you use Spring Boot 1.5, then the SpringBootServletInitializer is in the org.springframework.boot.web.support package, and if it’s Spring Boot 2.0, it’s in the org.springframework.boot.web.servlet.support package.

Deployment issues

If you try deploy a war file to JBoss (EAP 7, at least) in domain mode, and it fails, it shows an error on the console, So all well and good.

So the natural thing to do is to read the error, fix the issue in the war file, and retry the deployment.

Upon the attempt to redeploy, I’ve noticed two different issues recently:

1. It sticks on a random line, i.e. initialising Mojarra, and never continues until perhaps a timeout exception of some sort.

2. The war again fails to deploy but with a random error of sorts, i.e. Unable to register MBean [HikariDataSource…

Whilst I’m sure there are valid reasons for these issues, I figured out (what took longer than I care to admit) that the issue was the domain.xml file still held onto the initial deployment, even when shutting down the server.

If you check the <deployments> tag in the xml, the easiest solution is to manually remove the previously failed deployment (while JBoss is stopped), and then start it up again.

Sounds simple, but with the exceptions thrown being not obvious whatsoever, it is not easy unless you know the solution.

Wildfly 8.1 issues

I have also come across a number of issues trying to deploy a war file to Wildfly 8.1 (which deployed just fine to JBoss EAP 7 and Tomcat).

The first issue was along the lines of:

Error creating bean with name ‘httpPutFormContentFilter’… java.lang.VerifyError: Cannot inherit from final class

It appears to be something related to this issue, where Wildfly deploys its own version of Jackson, and messes up the deploy by not using the one you specified.

So, the fix is to create a jboss-deployment-structure.xml and add it to ./src/main/webapp :

<?xml version='1.0' encoding='UTF-8'?>

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.1">

<deployment>

<exclusions>

<module name="com.fasterxml.jackson.core.jackson-annotations" />

<module name="com.fasterxml.jackson.core.jackson-core" />

<module name="com.fasterxml.jackson.core.jackson-databind" />

<module name="com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider" />

<module name="org.jboss.resteasy.resteasy-jackson2-provider" />

</exclusions>

</deployment>

</jboss-deployment-structure>

Which led into the second issue I was having, a NullPointerException :

Caused by: java.lang.NullPointerException at java.util.ArrayList.<init>(ArrayList.java:177)

This apparently is an issue with using Wildfly 8.1, so the obvious fix is to upgrade to Wildfly 8.2…

However, for those that can’t upgrade, there is a workaround:

Download this undertow package

Open .\undertow-1.0.15.Final\servlet\src\main\java\io\undertow\servlet\spec\HttpServletResponseImpl.java

Find this part:

@Override

public Collection<String> getHeaders(final String name) {

return new ArrayList<String>(exchange.getResponseHeaders().get(name));

}

and replace it with:

@Override

public Collection<String> getHeaders(final String name) {

final HeaderValues headerValues = exchange.getResponseHeaders().get(name);

if (headerValues != null) {

return new ArrayList<String>(headerValues);

}

return new ArrayList<String>();

}

Note: the HeaderValues class is from the package io.undertow.util.HeaderValues;

Go to .\undertow-1.0.15.Final\servlet

Run mvn package

Replace the undertow-servlet-1.0.15.Final.jar in <WildFly_Home>/modules/system/layers/base/io/undertow/servlet/main with the one in <UnderTow_Root>/servlet/target/

Rebuild project and this will fix those issues.

Conclusion

I have ran through some of the common issues I’ve experienced when building and deploying Spring Boot applications to a JBoss server.

So at this point, I hope you have been successful with your own deployment, and that this article helped resolve any issues that you encountered.