Reputation: 1234
I'm having issues getting a simple hello world application to work on Wildfly 8.x. The stack trace I receive is a null pointer exception getting the headers of the response:
2016-07-15 04:14:28,488 ERROR [org.springframework.boot.context.web.ErrorPageFilter] (default task-4) Forwarding to error page from request [/hello] due to exception [null]: java.lang.NullPointerException
at java.util.ArrayList.<init>(ArrayList.java:177) [rt.jar:1.8.0_92]
at io.undertow.servlet.spec.HttpServletResponseImpl.getHeaders(HttpServletResponseImpl.java:248) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at javax.servlet.http.HttpServletResponseWrapper.getHeaders(HttpServletResponseWrapper.java:303) [jboss-servlet-api_3.1_spec-1.0.0.Final.jar:1.0.0.Final]
at org.springframework.http.server.ServletServerHttpResponse$ServletResponseHttpHeaders.get(ServletServerHttpResponse.java:160) [spring-web-4.2.7.RELEASE.jar:4.2.7.RELEASE]
at org.springframework.http.server.ServletServerHttpResponse$ServletResponseHttpHeaders.containsKey(ServletServerHttpResponse.java:142) [spring-web-4.2.7.RELEASE.jar:4.2.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.addContentDispositionHeader(AbstractMessageConverterMethodProcessor.java:346) [spring-webmvc-4.2.7.RELEASE.jar:4.2.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:238) [spring-webmvc-4.2.7.RELEASE.jar:4.2.7.RELEASE]
I threw together the quickest simplest Spring Boot restful service I could imagine:
package com.tryme;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TrymeController {
@RequestMapping(value="/hello")
public ResponseEntity<String> hello()
{
return new ResponseEntity<String>("Hello world.", HttpStatus.OK);
}
}
The application main is:
package com.tryme;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan
public class TrymeApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(TrymeApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(TrymeApplication.class);
}
}
I read several blog posts advising how to change your pom to support restful spring services, and this is the POM I created (I tried with both 3.1 servlet and 2.5).
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tryme</groupId>
<artifactId>tryme</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>tryme</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.6.RELEASE</version>
</parent>
<properties>
<start-class>com.tryme.TrymeApplication</start-class>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
-->
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-el</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<!--We are building spring boot application with maven-->
<build>
<finalName>tryme</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<!--Repositories for spring libs-->
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>http://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>http://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<!--Repositories for needed plugins -->
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>http://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>http://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
I tried forcing headers on my ResponseEntities, and it did't help. Can anyone tell me if there's anything I can change to get this simple app up and running with Spring Rest on 8.x Wildfly? I verified it works fine on 9.x and 10.x
Edit: here is what my latest war looks like.
Upvotes: 2
Views: 2442
Reputation: 5603
There is a bug in Undertow < 1.1.0-Final. Wildfly 8.1 uses Undertow 1.0.15.
In Untertow 1.0.x the getHeaders(String)
method does not check the response headers for null
.
// from Undertow 1.0.15-final
// http://grepcode.com/file/repo1.maven.org/maven2/io.undertow/undertow-servlet/1.0.15.Final/io/undertow/servlet/spec/HttpServletResponseImpl.java#HttpServletResponseImpl.getHeaders%28java.lang.String%29
@Override
public Collection<String> getHeaders(final String name) {
return new ArrayList<String>(exchange.getResponseHeaders().get(name));
}
From Undertow 1.1.0 upwards the getHeaders(String)
the methods checks the responseHeaders for null
// from Undertow 1.1.0-final
// http://grepcode.com/file/repo1.maven.org/maven2/io.undertow/undertow-servlet/1.1.0.Final/io/undertow/servlet/spec/HttpServletResponseImpl.java#HttpServletResponseImpl.getHeader%28java.lang.String%29
@Override
public Collection<String> getHeaders(final String name) {
HeaderValues headers = exchange.getResponseHeaders().get(name);
if(headers == null) {
return Collections.emptySet();
}
return new ArrayList<>(headers);
}
Unfortunately I have not found the corresponding bug report in the JBoss / Undertow issue tool.
So the only way to overcome this is to patch / overwrite the io.undertow.servlet.spec.HttpServletResponseImpl
Update the old jars in modules/system/layers/base/io/undertow/
with new ones
You have to modify the module.xml
in the corresponding directory.
Not sure about
For your example it's enough to update core and servlet. Better upgrade to the latest wildly 8.2 release if possible.
See also discussion on the JBoss forum
Upvotes: 6