Как правильно использовать EntityManager из сервиса RESTEasy?(SEAM, JBoss) - PullRequest
0 голосов
/ 20 октября 2011

Мой проект - проект WAR, созданный с помощью seam-gen. Он содержит такой класс веб-службы RESTEasy (упрощенно, только соответствующие части):

@Scope(ScopeType.APPLICATION)
public abstract class RestService {

    @In
    protected EntityManager entityManager;

    @GET
    @POST
    @Produces("application/json")
    public Object proxy() {
        // invokes various subclass methods
        // based on request parameters
        // and returns the result
    }
    // further method and logic
}

И

@Path("/my")
@Name("myRestService")
public class MyRestService extends RestService {

    public Object login(/*...*/) {
        User user = getUser(email);

        // ...

        Token token = user.getToken();
        if (token != null) {
            entityManager.remove(token);
        }
        token = new Token();
        entityManager.persist(token);
        user.setToken(token);
        user.setLastlogin(new Date());
        entityManager.persist(user);

        // ...
    }

    private User getUser(String email) {
        try {
            return (User) entityManager
                    .createQuery("FROM User WHERE UPPER(email) = UPPER(:email)")
                    .setParameter("email", email)
                    .getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
    }
}

Если я вызываю метод входа в систему через веб-браузер, он находит правильного пользователя (на основе параметров get), создает для него токен (я могу видеть в STDOUT Hibernate, запрашивая базу данных для следующей последовательности), но метод persist () не сохраняет токен в базе данных и не изменяет объект User (идентификатор токена, дату последнего входа в систему).

Я уже два дня гуглял, вот что я могу выяснить:

  • мой проект использует транзакции, управляемые SEAM (components.xml):

    <persistence:managed-persistence-context name="entityManager" auto-create="true"
                       persistence-unit-jndi-name="java:/MyEntityManagerFactory"/>
    
  • мой проект использует JTA для обработки транзакций (persistence.xml):

    <persistence-unit name="MyProject" transaction-type="JTA">
        <provider>org.hibernate.ejb.HibernatePersistence</provider> ...
    
  • EntityManager.persist () НЕ фиксирует изменения в базе данных, просто помещает в очередь изменения в текущей транзакции (?)

  • Операции, управляемые SEAM, по умолчанию привязаны к разговорам

Я пытался использовать .flush (), было сгенерировано исключение о том, что транзакция не выполняется.

Я пытался использовать .joinTransaction () и .getTransaction (). Begin (), было выдано другое исключение, сообщающее, что JTA EntityManager не может получить доступ к транзакциям.

Также пытался использовать разные типы областей действия в классе или использовать аннотацию @Transactional в моем методе login (), не повезло.

Также пытался внедрить EntityManager с аннотацией @PersistenceContext, это привело к исключению, сказав, что @PersistenceContext может использоваться только с сеансными компонентами.

Также попытался пометить мой класс как @Stateless, в результате чего я не смог обратиться к своему сервису (404).

Как мне сохранить мои сущности в службе RESTEasy с EntityManager?

Технические характеристики системы:

  • JBoss 5.1.0 GA
  • ШВ 2.2.1 Финал
  • Postgres 8,3

Обратите внимание, что я совершенно новый и неопытный с JavaEE / JBoss / SEAM.

Любой комментарий будет полезен! Благодаря.

Ответы [ 2 ]

1 голос
/ 25 октября 2011

Вы отключаете управляемое поле:

entityManager.remove(token);

Создание нового:

token = new Token();

Но здесь:

entityManager.persist(token);

Токен имеет связь с пользователем (я не знаю, что это за связь - oneToMany, oneToOne, вы каскадируете от пользователя? Посмотрите здесь http://www.objectdb.com/java/jpa/persistence/crud

0 голосов
/ 26 октября 2011

Транзакционная аннотация важна для метода входа в систему.Это гарантирует, что перехватчик транзакции создает транзакцию, если это необходимо.(если еще нет транзакции).Самый простой способ узнать, применяется ли перехватчик, - это отладить метод входа в систему и проверить стек.Я не уверен, как называется класс, но я обновлю этот пост, как только я на работе, чтобы проверить его.Если этот перехватчик отсутствует, это означает, что вы не используете шовные транзакции.Выдержка из вашего component.xml не показывает, что вы делаете это.

Мартин

Обновлено: так вот трассировка стека.Посмотрите на TransactionInterceptor, если у вас его нет в стеке, у вас нет управления транзакциями.

Daemon Thread [http-18081-1] (Suspended (breakpoint at line 170 in QueryHome))  
    QueryHome.getCandidatesCount() line: 170    
    NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]  
    NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39  
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25  
    Method.invoke(Object, Object...) line: 597  
    Reflections.invoke(Method, Object, Object...) line: 22  
    RootInvocationContext.proceed() line: 32    
    SeamInvocationContext.proceed() line: 56    
    RollbackInterceptor.aroundInvoke(InvocationContext) line: 28    
    SeamInvocationContext.proceed() line: 68    
    BijectionInterceptor.aroundInvoke(InvocationContext) line: 77   
    SeamInvocationContext.proceed() line: 68    
    ConversationInterceptor.aroundInvoke(InvocationContext) line: 65    
    SeamInvocationContext.proceed() line: 68    
    TransactionInterceptor$1.work() line: 97    
    TransactionInterceptor$1(Work<T>).workInTransaction() line: 61  
    TransactionInterceptor.aroundInvoke(InvocationContext) line: 91 
    SeamInvocationContext.proceed() line: 68    
    MethodContextInterceptor.aroundInvoke(InvocationContext) line: 44   
    SeamInvocationContext.proceed() line: 68    
    JavaBeanInterceptor(RootInterceptor).invoke(InvocationContext, EventType) line: 107 
    JavaBeanInterceptor.interceptInvocation(Method, Object[]) line: 185 
    JavaBeanInterceptor.invoke(Object, Method, Method, Object[]) line: 103  
...