当将企业bean注入JAX-RS 2.0 REST服务时,NullPointerException异常 [英] NullPointerException when inject enterprise bean into JAX-RS 2.0 REST service

查看:382
本文介绍了当将企业bean注入JAX-RS 2.0 REST服务时,NullPointerException异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将EJB 3.1注入我的RESTful服务之一。我遵循了这个职位:将EJB注入JAX-RS(RESTful服务),并尝试所有选项,除了构建注入提供程序。我正在尝试的当前解决方案使用 @RequestScoped @Inject 的组合,但是我注入的bean变量仍然是。我在 / WEB-INF 文件夹中有一个 beans.xml



如何将EJB注入到我的REST服务类中?



UserService

 @Local 
@Path(user / v1)
@Produces(MediaType.APPLICATION_JSON)
public class UserServiceV1实现SystemLogger {

@Inject
private ApplicationBean appBean;

@GET
@Path(pingbean)
@Produces(MediaType.APPLICATION_JSON)
public Response pingAppBean(){
if(appBean = = null){
return Response.status(Response.Status.UNAUTHORIZED).entity({\faild\:\App bean is null\)
}
String message = appBean.getHello();
return Response.status(Response.Status.OK)
.entity(message)
.build();
}
}

ApplicationBean
SystemHandler 驻留在jar模块中,是具有业务逻辑的标准类。

  @Stateless 
@Local
public class ApplicationBean实现ApplicationBeanLocal {

@Override
public String getHello(){
返回来自ApplicationBean的Hello;
};
}

JAX-RS配置

  @ApplicationPath(service)
public class ApplicationService extends Application {

@Override
public Set< Class& ;> getClasses(){
Set< Class<?>> resources = new HashSet;();
resources.add(UserServiceV1.class);
resources.add(ApplicationBean.class);
resources.add(CorsFilterProvider.class);
返回资源;
}
}

异常

  14:07:01,230 ERROR [io.undertow.request] UT005023:异常处理请求到/ MyApp / service / user / v1 / login:org.jboss.resteasy。 spi.UnhandledException:java.lang.NullPointerException 
在org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:76)[resteasy-jaxrs-3.0.14.Final.jar:3.0.14.Final ]
在org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:212)[resteasy-jaxrs-3.0.14.Final.jar:3.0.14.Final]

Resteasy / JAX-RS
我已经根据文档

 <依赖性> 
< groupId> org.jboss.resteasy< / groupId>
< artifactId> resteasy-jaxrs< / artifactId>
< version> 3.0.14.Final< / version>
< scope>已提供< / scope>
< / dependency>
<依赖关系>
< groupId> org.jboss.resteasy< / groupId>
< artifactId> resteasy-cdi< / artifactId>
< version> 3.0.14.Final< / version>
< scope>已提供< / scope>
< / dependency>

编辑:更改问题标题中的代码详细信息

解决方案

正如Steve C回答的那样,在JAX-RS 1.1中注入EJB的正确方法是使用javax.ejb.EJB注释。 REST服务也必须是EJB才能使其工作。因此,您必须使用javax.ejb.Stateless注释而不是javax.enterprise.context.RequestScoped。



最终结果如下:

  @Stateless 
@Path(user / v1)
public class UserServiceV1实现SystemLogger {
@ EJB
private ApplicationBean appBean;

//等。
}



编辑



您更新的代码未部署。要么有 ApplicationBean 实现 ApplicationBeanLocal 并注入接口,或者不实现它并直接注入该类。有了这个更正,我设法运行你的例子很好。



另外,在 ApplicationService 中,你不需要添加 ApplicationBean.class 。您只注册REST根资源和功能提供商。 @Local UserServiceV1 类中也是不必要的,它不是EJB。



此外,它是 beans.xml ,而不是 bean.xml (但是这个文件不是必需的



请参阅下面的测试代码:



pom。 xml jar模块的依赖项:

 <依赖关系> 
<依赖关系>
< groupId> javax.ejb< / groupId>
< artifactId> javax.ejb-api< / artifactId>
< version> 3.2< / version>
< / dependency>
< / dependencies>

ApplicationBeanLocal.java

  public interface ApplicationBeanLocal {
String getHello();
}

ApplicationBean.java

  @Stateless 
@Local
public class ApplicationBean实现ApplicationBeanLocal {
@Override
public String getHello(){
返回来自ApplicationBean的Hello;
}
}

pom.xml JAX-RS应用程序的依赖关系:

 <依赖关系> 
<依赖关系>
< groupId> org.jboss.resteasy< / groupId>
< artifactId> resteasy-jaxrs< / artifactId>
< version> 3.0.14.Final< / version>
< scope>已提供< / scope>
< / dependency>
<依赖关系>
< groupId> org.jboss.resteasy< / groupId>
< artifactId> resteasy-cdi< / artifactId>
< version> 3.0.14.Final< / version>
< scope>已提供< / scope>
< / dependency>
<依赖关系>
< groupId> javax.enterprise< / groupId>
< artifactId> cdi-api< / artifactId>
< version> 1.2< / version>
< scope>已提供< / scope>
< / dependency>

<! - 包含ApplicationBean和ApplicationBeanLocal的jar模块 - >
<依赖关系>
< groupId> test< / groupId>
< artifactId> testjar&​​lt; / artifactId>
< version> 0.0.1-SNAPSHOT< / version>
< / dependency>
< / dependencies>

TestApplication.java

  @ApplicationPath(service)
public class TestApplication extends Application {

private final Set< Class< ;?>> resources = new HashSet;();

public TestApplication(){
resources.add(UserServiceV1.class);
}

@Override
public Set< Class<?>> getClasses(){
返回资源;
}
}

UserServiceV1.java

  @Path(user / v1)
@RequestScoped
@Produces (MediaType.APPLICATION_JSON)
public class UserServiceV1 {

@Inject //请注意,我引用了接口,而不是实现
private ApplicationBeanLocal appBean;

@GET
@Path(pingbean)
@Produces(MediaType.APPLICATION_JSON)
public Response pingAppBean(){
final String message = appBean.getHello();
return Response.status(Response.Status.OK).entity(message).build();
}
}


I am trying to inject and EJB 3.1 in one of my RESTful services. I've followed the post: Inject an EJB into JAX-RS (RESTful service) and tried all options except building an injection provider. The current solution that I am trying uses a combination of @RequestScoped and @Inject, but my injected bean variable is still null. I have a beans.xml in the /WEB-INF folder.

How can I inject an EJB into my REST service class?

UserService

@Local   
@Path("user/v1")
@Produces(MediaType.APPLICATION_JSON)
public class UserServiceV1 implements SystemLogger {

    @Inject
    private ApplicationBean appBean;

    @GET
    @Path("pingbean")
    @Produces(MediaType.APPLICATION_JSON)
    public Response pingAppBean() {
        if(appBean == null) {
            return Response.status(Response.Status.UNAUTHORIZED).entity("{\"faild\": \"App bean is null\"}").build();
        }
        String message = appBean.getHello();
        return Response.status(Response.Status.OK)
                .entity(message)
                .build();
    }
}

ApplicationBean The SystemHandler resides in jar module and is a standard class with business logic.

@Stateless
@Local
public class ApplicationBean implements ApplicationBeanLocal {

    @Override
    public String getHello() {
        return "Hello from ApplicationBean";
    };
}

JAX-RS configuration

@ApplicationPath("service")
public class ApplicationService extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> resources = new HashSet<>();
        resources.add(UserServiceV1.class);
        resources.add(ApplicationBean.class);
        resources.add(CorsFilterProvider.class);
        return resources;
    }
}

Exception

14:07:01,230 ERROR [io.undertow.request] UT005023: Exception handling request to /MyApp/service/user/v1/login: org.jboss.resteasy.spi.UnhandledException: java.lang.NullPointerException
        at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:76) [resteasy-jaxrs-3.0.14.Final.jar:3.0.14.Final]
        at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:212) [resteasy-jaxrs-3.0.14.Final.jar:3.0.14.Final]

Resteasy /JAX-RS I've added a CDI implementation for resteasy according to the documentation

<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jaxrs</artifactId>
    <version>3.0.14.Final</version>
    <scope>provided</scope>
</dependency>
<dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-cdi</artifactId>
        <version>3.0.14.Final</version>
        <scope>provided</scope>
 </dependency>

EDIT: changed code details in the question and title

解决方案

As Steve C answered, the proper way to inject an EJB in JAX-RS 1.1 is with the javax.ejb.EJB annotation. The REST service must also be an EJB for this to work. As such, you have to use the javax.ejb.Stateless annotation instead of javax.enterprise.context.RequestScoped.

The end result is as follows:

@Stateless
@Path("user/v1")
public class UserServiceV1 implements SystemLogger {
    @EJB
    private ApplicationBean appBean;

    //etc.
}

EDIT

Your updated code doesn't deploy. Either have ApplicationBean implement ApplicationBeanLocal and inject the interface, or don't implement it and inject the class directly. With that corrected, I managed to run your example just fine.

Also, in ApplicationService, you don't need to add ApplicationBean.class. You only register there REST root resources and feature providers. @Local is also unnecessary in the UserServiceV1 class, it's not an EJB.

Furthermore, it's beans.xml, not bean.xml (but this file is not necessary anymore from CDI 1.1 on).

See my testcode below:

pom.xml dependencies for the jar module:

<dependencies>
    <dependency>
        <groupId>javax.ejb</groupId>
        <artifactId>javax.ejb-api</artifactId>
        <version>3.2</version>
    </dependency>
</dependencies>

ApplicationBeanLocal.java:

public interface ApplicationBeanLocal {
    String getHello();
}

ApplicationBean.java:

@Stateless
@Local
public class ApplicationBean implements ApplicationBeanLocal {
    @Override
    public String getHello() {
        return "Hello from ApplicationBean";
    }
}

pom.xml dependencies for the JAX-RS application:

<dependencies>
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jaxrs</artifactId>
        <version>3.0.14.Final</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-cdi</artifactId>
        <version>3.0.14.Final</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.enterprise</groupId>
        <artifactId>cdi-api</artifactId>
        <version>1.2</version>
        <scope>provided</scope>
    </dependency>

    <!-- The jar-module containing ApplicationBean and ApplicationBeanLocal -->
    <dependency>
        <groupId>test</groupId>
        <artifactId>testjar</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
</dependencies>

TestApplication.java:

@ApplicationPath("service")
public class TestApplication extends Application {

    private final Set<Class<?>> resources = new HashSet<>();

    public TestApplication() {
        resources.add(UserServiceV1.class);
    }

    @Override
    public Set<Class<?>> getClasses() {
        return resources;
    }
}

UserServiceV1.java

@Path("user/v1")
@RequestScoped
@Produces(MediaType.APPLICATION_JSON)
public class UserServiceV1 {

    @Inject // Note that I'm referencing the interface, not the implementation
    private ApplicationBeanLocal appBean;

    @GET
    @Path("pingbean")
    @Produces(MediaType.APPLICATION_JSON)
    public Response pingAppBean() {
        final String message = appBean.getHello();
        return Response.status(Response.Status.OK).entity(message).build();
    }
}

这篇关于当将企业bean注入JAX-RS 2.0 REST服务时,NullPointerException异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆