Как обработать контекст постоянства (EntityManager) с помощью локаторов jax-rs? - PullRequest
4 голосов
/ 20 апреля 2011

Я использую в своем приложении web-сервис jax-rs restful с локаторами подресурсов. Однако после передачи 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 на подресурс, чтобы он мог правильно сохранять новые объекты?

Ответы [ 2 ]

5 голосов
/ 04 февраля 2013

Извините, что выкопал это снова, но я предлагаю следующее:

  • Аннотируйте также подресурс как @Stateless EJB
  • Поместите поля-члены @EJB-инъекции в родительский класс ресурсов, например:
        @EJB private RegistrationResource registrationResource;
    
  • в "getRegistrationResource ()", не вызывайте конструктор подресурса, но возвращайте вставленную ссылку EJB:
    public RegistrationResource getRegistrationResource() {
        return this.registrationResource;
    }

Однако, чтобы это работало, вы не можете передать "@PathParam" в качестве параметра конструктора. Вам нужно было бы получить к нему отдельный доступ во вложенном ресурсе через "@Context" или другое объявление @Path.
Это позволяет вам внедрить EntityManager в подресурс точно так же, как в родительском ресурсе, вам не нужно его передавать.

3 голосов
/ 28 февраля 2012

Возможно, слишком поздно, но в любом случае ... Когда вы возвращаете свой подресурс, вы «покидаете» компонент без сохранения состояния. Поскольку контейнер управляет транзакцией, транзакция фиксируется при возврате из RegistrationsResource.

Затем Джерси создаст ваш подресурс, но это не bean-компонент без состояния, поэтому у вас не будет транзакции, управляемой контейнером. Отсюда и исключение.

Я бы посоветовал вам поместить вашу бизнес-логику в новый класс, который вы затем создадите в качестве компонента без состояния. Здесь вы выполняете всю работу с базой данных, которая всегда обрабатывается в управляемой контейнером транзакции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...