我在带有子资源定位器的应用程序中使用jax-rs rest式web服务。然而,在将entityManager传递给子资源后,我不能在该子资源中持久化任何新对象。
entityManager允许我查询数据。
这是我的主要资源
@Path("/registrations")
@Stateless
public class RegistrationsResource {
@Context
private UriInfo context;
@PersistenceContext(unitName="pctx")
private EntityManager em;
public RegistrationsResource() {
}
//POST method ommited
@Path("{regKey}")
public RegistrationResource getRegistrationResource(@PathParam("regKey")
String regKey) {
return RegistrationResource.getInstance(regKey, em);
}
}
这是我的子资源:public class RegistrationResource {
private String regKey;
private EntityManager em;
private RegistrationResource(String regKey, EntityManager em) {
this.regKey = regKey;
this.em = em;
}
@Path("securityQuestion")
@GET
public String getQuestion() {
return "iamahuman"+regKey;
}
@Path("securityQuestion")
@POST
public void postSecurityAnswer(String answer) {
if(!answer.equals("iamahuman"+regKey)){
throw new WebApplicationException(Status.BAD_REQUEST);
}
//Getting this information works properly
List<RegistrationEntity> result = em.createNamedQuery("getRegistrationByKey")
.setParameter("regKey", regKey).getResultList();
switch(result.size()){
case 0 :
throw new WebApplicationException(Status.NOT_FOUND);
case 1:
break;
default:
throw new WebApplicationException(Status.INTERNAL_SERVER_ERROR);
}
RegistrationEntity reg = result.get(0);
UserEntity newUser = new UserEntity();
newUser.setHashedPassword(reg.getPwHash(), reg.getSalt());
newUser.setUsername(reg.getUsername());
newUser.setName(reg.getName());
newUser.setSurname(reg.getSurname());
//CRASHES HERE
em.persist(newUser);
}
}
可以看到,它从数据库中获取注册对象,为注册创建新用户并尝试持久化它。但是,em.persist(newUser)抛出TransactionRequiredException。
我的问题是:我应该如何将EntityManager传递给子资源,以便它可以正确地持久化新对象?
很抱歉再次挖掘这个问题,但我建议如下:
- 还将子资源注释为@无状态EJB
- 将@EJB注入成员字段放入父资源类中,如下所示:<>之前ejb私有注册资源之前
- 在"getRegistrationResource()"中,不调用子资源的构造函数,而是返回注入的EJB引用:
public RegistrationResource getRegistrationResource() {返回this.registrationResource;}
工作,您不能将"@PathParam"作为构造函数参数传递。你必须通过"@Context"或另一个@Path声明在子资源中单独访问它。
这使得你可以像在父资源中一样在子资源中注入EntityManager,而不需要传递它。
可能太晚了,但无论如何…当你返回子资源时,你就"离开"了无状态bean。当容器管理事务时,事务将在您从RegistrationsResource返回时提交。
Jersey将构造你的子资源,但它不是一个无状态bean,所以你不会有一个容器管理的事务。因此出现了例外。我建议你把你的业务逻辑放在一个新的类中,然后把它变成一个无状态bean。这里你做所有数据库的东西,然后总是在容器管理的事务中处理。