我在 Spring Boot 上有一个使用 JAX-RS、JPA 的简单服务。它在 Tomcat 上运行良好,但当我部署在 WildFly 10 中时,我收到服务的 NPE(以及网页上的 Err 500),该服务使用 Jpa 查询数据库。不使用 jpa-query 的服务工作正常。这是我的配置:
pom.xml:
groupId>com.github.naut92.animalswebservice</groupId>
<artifactId>animalsrestservice</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>AnimalsRestService</name>
<description>Restful project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<start-class>com.github.naut92.animalswebservice.AnimalsRestServiceApplication</start-class>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</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-web-services</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- thymeleaf used case-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- tag::security[] -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- end::security[] -->
</dependencies>
<build>
<!--name project for deploying in Enterprise Servers-->
<finalName>animals-rest</finalName>
<plugins>
<!--plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin-->
<plugin>
<groupId>org.jboss.as.plugins</groupId>
<artifactId>jboss-as-maven-plugin</artifactId>
<version>7.9.Final</version>
<executions>
<execution>
<id>jboss-deploy</id>
<phase>pre-integration-test</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
<execution>
<id>jboss-undeploy</id>
<phase>post-integration-test</phase>
<goals>
<goal>undeploy</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<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>
<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>
JerseyConfig 类:
@ApplicationPath("/index")
@Configuration
public class JerseyConfig extends ResourceConfig /*Application*/ {
public JerseyConfig() {
register(CustomerResource.class);
}
服务等级:
@Component
@Path("/cust")
public class CustomerResource {
@Inject
private /*final*/ CustomersRepository customersRepository;
public CustomerResource(CustomersRepository customersRepository){
this.customersRepository = customersRepository;
}
public CustomerResource() {
}
//TEST--------------------------------
@GET
@Path(value = "/ajaxtest")
@Produces("application/json")
public Set<String> ajaxTest() {
Set<String> records = new HashSet<String>();
records.add("Record #1");
records.add("Record #2");
return records;
}
@GET
@Path(value = "/all")
@Produces("application/json")
public Collection<CustomersEntity> listCustomers() {
return (Collection<CustomersEntity>) customersRepository.findAll();
}
@GET
@Path("/all/{id}")
@Produces("application/json")
public CustomersEntity getCustomerById(@PathParam(value = "id") Long id) throws NotFoundException {
CustomersEntity customer;
if(customersRepository.exists(id)){
customer = customersRepository.findOne(id);
}
else
throw new NotFoundException("could not find user '" + id + "'.");
return customer;
}
}
和 ajaxTest() 方法工作正常,但其他两个不起作用:
java.lang.NullPointerException
at com.github.naut92.animalswebservice.resourcesService.CustomerResource.listCustomers(CustomerResource.java:58)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:139)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:295)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:249)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:236)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:402)
我尝试对 spring-boot-starter-tomcat 使用
<exclusions>
,就像在 this 教程和 spring-boot-starter-websocket 中一样,但我总是遇到同样的错误。
这是因为 Jersey 没有被使用。您可以看出例外的是正在使用 RESTEasy(Wildlfy 的 JAX-RS 实现)。原因是因为
@ApplicationPath
类上的 ResourceConfig
注释。 ResourceConfig
是标准 JAX-RS Application
类的扩展。 JAX-RS 旨在选取带有 Application
注释的 @ApplicationPath
类。
因此在启动时,RESTEasy 正在创建应用程序,而不是 Spring Boot。这就是NPE的原因。 RESTEasy 创建资源类,调用默认构造函数,其中服务未初始化。并且您尝试在请求期间调用未初始化的服务。
现在我不知道这是否可行,因为我从未尝试过部署到 Wildfly,但您需要修复的主要问题是:
移除
@ApplicationPath
,这样 RESTEasy 就不会拾取它。您可以在 applicaiton.properties
文件中配置路径。只需使用属性spring.jersey.application-path
您需要确保您的 Spring Boot“应用程序”类扩展
SpringBootServletInitializer
。这允许容器在启动时拾取应用程序。这就是 Spring Boot 初始化应用程序的方式。