Spring Boot + Wildfly 10 中 jpa 查询的 jax-rs 服务中的 NPE

问题描述 投票:0回答:1

我在 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 中一样,但我总是遇到同样的错误。

spring-boot jersey jax-rs spring-data-jpa wildfly
1个回答
1
投票

这是因为 Jersey 没有被使用。您可以看出例外的是正在使用 RESTEasy(Wildlfy 的 JAX-RS 实现)。原因是因为

@ApplicationPath
类上的
ResourceConfig
注释。
ResourceConfig
是标准 JAX-RS
Application
类的扩展。 JAX-RS 旨在选取带有
Application
注释的
@ApplicationPath
类。

因此在启动时,RESTEasy 正在创建应用程序,而不是 Spring Boot。这就是NPE的原因。 RESTEasy 创建资源类,调用默认构造函数,其中服务未初始化。并且您尝试在请求期间调用未初始化的服务。

现在我不知道这是否可行,因为我从未尝试过部署到 Wildfly,但您需要修复的主要问题是:

  1. 移除

    @ApplicationPath
    ,这样 RESTEasy 就不会拾取它。您可以在
    applicaiton.properties
    文件中配置路径。只需使用属性
    spring.jersey.application-path

  2. 您需要确保您的 Spring Boot“应用程序”类扩展

    SpringBootServletInitializer
    。这允许容器在启动时拾取应用程序。这就是 Spring Boot 初始化应用程序的方式。

© www.soinside.com 2019 - 2024. All rights reserved.