使用EJB开发RESTful应用部署Glassfish时遇空指针异常求助
解决Glassfish中EJB注入REST服务时的NullPointerException问题
看起来你在把基于EJB的REST应用部署到Glassfish时遇到了NullPointerException,这通常是因为EJB没有被正确注入导致的。结合你提供的代码和配置,我来梳理一下可能的问题点和解决办法:
你的当前配置回顾
db.jar中的远程接口
@Remote public interface DBManagerRemote { // 接口方法 }
restful.war中的注入代码
@EJB private DBManagerRemote manager;
web.xml配置
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <display-name>Restful Web Application</display-name> <context-param> <param-name>resteasy.scan</param-name> <param-value>true</param-value> </context-param> <listener> <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class> </listener> <servlet> <servlet-name>resteasy-servlet</servlet-name> <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class> </servlet> <servlet-mapping> <servlet-name>resteasy-servlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
db.jar中的persistence.xml
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="simpleFactory" transaction-type="JTA"> <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> <jta-data-source>source_name</jta-data-source> <class>Mybean</class> </persistence-unit> </persistence>
可能的问题及解决方案
1. 缺少EJB实现类
你只提供了DBManagerRemote远程接口,但EJB容器需要一个带有EJB注解(比如@Stateless、@Stateful)的实现类才能创建可管理的EJB实例。没有实现类的话,容器无法生成代理对象注入到你的REST服务中,自然会出现NPE。
解决办法:
在db.jar中添加实现类,并加上@Stateless注解:
@Stateless public class DBManager implements DBManagerRemote { // 实现接口中的所有方法 }
2. REST服务类未被容器管理
你的REST服务类如果只是简单用@Path注解,但没有被Java EE容器(EJB或CDI)管理的话,@EJB注入不会生效——因为只有容器管理的Bean才能享受依赖注入的能力。
解决办法:
有两种方式可以处理:
- 把REST服务做成EJB:在你的REST类上同时添加
@Path和@Stateless注解:@Path("/myapi") @Stateless public class MyRestService { @EJB private DBManagerRemote manager; // 比如一个GET接口 @GET @Path("/test") public String testDbAccess() { // 使用manager操作数据库 return "Success"; } } - 启用CDI管理:如果不想把REST类做成EJB,就在restful.war的
WEB-INF目录下添加一个空的beans.xml文件,启用CDI支持,然后给REST类加上@RequestScoped(或其他CDI作用域注解):
然后修改REST类:<!-- WEB-INF/beans.xml --> <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd" version="2.0" bean-discovery-mode="all"> </beans>@Path("/myapi") @RequestScoped public class MyRestService { @EJB private DBManagerRemote manager; // ... }
3. 部署依赖关系问题
如果db.jar和restful.war是分开部署的,或者依赖关系没有配置正确,restful.war的类加载器可能无法访问到db.jar中的EJB类,导致注入失败。
解决办法:
- 推荐把两个模块打包成一个EAR文件,确保EAR的
application.xml中正确声明两个模块:<!-- application.xml --> <application xmlns="http://java.sun.com/xml/ns/javaee" version="6"> <module> <ejb>db.jar</ejb> </module> <module> <web> <web-uri>restful.war</web-uri> <context-root>/restful</context-root> </web> </module> </application> - 或者把db.jar直接放到restful.war的
WEB-INF/lib目录下(适合本地开发测试场景)。
4. Resteasy与Glassfish自带JAX-RS的冲突
Glassfish默认使用Jersey作为JAX-RS实现,而你用了Resteasy,这两者可能会产生类加载冲突,导致容器无法正确处理EJB注入。
解决办法:
- 要么改用Glassfish自带的Jersey,移除Resteasy相关的依赖和配置,使用标准的JAX-RS注解,这样集成会更顺畅;
- 如果坚持用Resteasy,需要在web.xml中添加配置禁用Glassfish的默认JAX-RS实现,比如添加:
同时确保所有Resteasy的依赖包都正确打包到restful.war中。<context-param> <param-name>javax.ws.rs.Application</param-name> <param-value>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</param-value> </context-param>
按照以上步骤逐一排查,应该能解决你的NPE问题。
内容的提问来源于stack exchange,提问作者Daniel Mur
相关产品推荐
相关产品推荐

