我正在试图弄清楚如何在我的应用程序中设置Service / Dao图层。我发现了几十种资源都有不同的方法来决定如何做,并决定按照这里找到的模型:How should EntityManager be used in a nicely decoupled service layer and data access layer?
我无法弄清楚我错过了什么导致了这个NPE。
用法:
@Path("/helloworld")
public class MyController {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String TestRequest() {
Workflow workflow = new Workflow();
workflow.setName("test");
WorkflowService workflowService = new WorkflowService();
workflowService.save(workflow);
return "Workflow ID:";
}
}
我的道:
@Stateless
public class WorkflowDao {
@PersistenceContext(unitName = "unit")
private EntityManager entityManager;
public int save(Workflow workflow) {
entityManager.persist(workflow);
return workflow.getId();
}
}
我的服务:
@Stateless
public class WorkflowService {
@EJB
WorkflowDao workflowDao;
public int save(Workflow workflow) {
int id = workflowDao.save(workflow); //throws NullPointerException because workflowDao is null
return id;
}
}
这是我第一次设置一个Java项目(之前只使用过1次,并使用了Spring)所以如果这看起来非常糟糕,请记住这一点。
答案 0 :(得分:1)
WorkflowDao
不是EJB,它是带有@Stateless
注释的POJO。很自然地,用@EJB
注入它会失败,创建一个空workflowDao
属性并最终产生一个NullPointerException
。
要使WorkflowDao
成为一个成熟的EJB,除了具有@Stateless
或@Stateful
注释外,还需要实现本地,远程或两个接口,并且必须对这些接口进行注释分别与@Local
和@Remote
。有关详细信息,请参阅tutorial。
此外,很可能(这可能是依赖于应用程序服务器的)您必须在应用程序的xml描述符文件中注册EJB - 例如,在web.xml的<ejb-local-ref>
元素中。
作为旁注 - 将EJB用作DAO并不是一个好主意,EJB通常用于实现业务逻辑(可以从这里调用true,persist / merge操作),但现在的实际持久层是使用JPA实现。换句话说,WorkflowService
应该是 EJB服务,不需要将EJB注入其中,也不需要单独的DAO层 - JPA实体可以实现此角色。
答案 1 :(得分:1)
如果手动实例化WorkflowService,容器将不会执行任何注入,因为您的WorkflowService不由Container管理。
我建议你:
注释您的Jax-RS资源@Stateless
通过@EJB作为成员注入WorkfloService
不再需要实现本地或远程接口
@Path("workflows")
@Stateless
public class WorkFlowResource{
@EJB
WorkflowService workflowService;
@GET
@Produces(MediaType.TEXT_PLAIN)
public String TestRequest() {
Workflow workflow = new Workflow();
workflow.setName("test");
workflowService.save(workflow);
return "Workflow ID:";
}
}