How to handle persistence context (EntityManager) using jax-rs localization locators?

I am using jax-rs restful web service in my application with subresource locators. However, after passing the entityManager to a sub-resource, I cannot save any new objects in this sub-resource.

EntityManager allows me, however, to query it for data.

This is my main resource:

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

}

And this is my sub-resource:

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

As you can see, it takes the registration object from the database, creates a new user for registration and tries to save it. However, em.persist (newUser) throws a TransactionRequiredException.

My question is: how do I pass the EntityManager to a sub-resource so that it can correctly save new objects?

+4
source share
2 answers

Sorry for copying again, but I suggest the following:

  • Annotate also a sub-resource like @Stateless EJB
  • Put the fields of the @EJB input element in the parent resource class, for example:
      @EJB private RegistrationResource registrationResource;
    
  • in "getRegistrationResource ()", do not call the subresource constructor, but return the entered EJB link:
      public RegistrationResource getRegistrationResource () {
         return this.registrationResource;
     } 

For this, however, you cannot pass "@PathParam" as a constructor parameter. You will have to access it separately in the subresource via "@Context" or another @Path declaration.
This allows you to enter the EntityManager in the auxiliary resource in the same way as in the parent resource, you do not need to pass it.

+5
source

Perhaps too late, but in any case ... When you return your resource, you leave a "bezelless" bean. When the container manages the transaction, the transaction is committed when you return from RegistrationsResource.

Then, Jersey will build your auxiliary resource, but it is not a stand-alone bean, so you won’t have a container-managed transaction. Hence the exception.

I would advise you to put your business logic in a new class, which will then make the bean stand out. Here you do all of your databases, which are then processed in a container-managed transaction.

+3
source

All Articles