将企业bean注入JAX-RS 2.0 REST服务时出现NullPointerException

时间:2016-04-15 12:21:26

标签: rest java-ee ejb jax-rs wildfly

我正在尝试在我的一个RESTful服务中注入EJB 3.1。我已经关注了帖子:Inject an EJB into JAX-RS (RESTful service)并尝试了除构建注入提供程序之外的所有选项。我正在尝试的当前解决方案使用sd_cancel@RequestScoped的组合,但我注入的bean变量仍为@Inject。我在null文件夹中有一个beans.xml

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

UserService

/WEB-INF

ApplicationBean中 @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(); } } 驻留在jar模块中,是具有业务逻辑的标准类。

SystemHandler

JAX-RS配置

@Stateless
@Local
public class ApplicationBean implements ApplicationBeanLocal {

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

异常

@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;
    }
}

Resteasy / JAX-RS 我根据the documentation

添加了一个用于重新安装的CDI实现
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]

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

2 个答案:

答案 0 :(得分:0)

EJB 3.1意味着Java EE 6容器实现。 Java EE 6意味着JAX-RS 1.1。

JAX-RS 1.1仅需要支持@EJB注入企业java bean。

Java EE 7实现中提供的JAX-RS 2.0支持@Inject for EJB。

答案 1 :(得分:0)

正如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 implements SystemLogger {
    @EJB
    private ApplicationBean appBean;

    //etc.
}

修改

您的更新代码未部署。要么ApplicationBean实现ApplicationBeanLocal并注入接口,要么不实现它并直接注入类。经过纠正,我设法运行你的例子。

此外,在ApplicationService中,您无需添加ApplicationBean.class。您只在那里注册REST根资源和功能提供程序。 @Local类中也不需要UserServiceV1,它不是EJB。

此外,它是beans.xml,而不是bean.xml(但此CDI 1.1上不再需要此文件)。

请参阅下面的测试代码:

jar模块的

pom.xml依赖项:

<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";
    }
}
JAX-RS应用程序的

pom.xml依赖项:

<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();
    }
}