0

I've been trying to use Vaadin JPAContainer with a JTA datasource in JBoss, but I keep getting this error when committing a FieldGroup: "no transaction is in progress"

Here's my persistence.xml

    <persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">
   <persistence-unit name="Pagamento">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <jta-data-source>java:jboss/datasources/Pagamento</jta-data-source>  

      <class>br.com.edu.entidades.Usuario</class>

      <properties>
         <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"></property>         
         <property name="hibernate.cache.use_second_level_cache" value="false"></property>
         <property name="hibernate.hbm2ddl.auto" value="update"></property>
         <property name="hibernate.show_sql" value="false"></property>  
         <property name="hibernate.format_sql" value="true"></property>
      </properties>

   </persistence-unit>
</persistence>

I'm also using a custom EntityProvider in order to support JTA:

public class EduEntityProvider extends MutableLocalEntityProvider<Usuario> {     

    private EntityManager em = HibernateUtils.entityManager;

    public EduEntityProvider() {
        super(Usuario.class);
        setEntityManager(em);

        setEntitiesDetached(false);
        setTransactionsHandledByProvider(false);
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    protected void runInTransaction(Runnable operation) {
        super.runInTransaction(operation);
    }    

}

The Entity:

@SuppressWarnings("serial")
@Entity
@Table(name="usuario")
public class Usuario extends EduPersistentEntity {

    @Id
    @Column(name="id")
    @VisivelTabela(false)
    private String id;

    @Column(name="nome")
    private String nome;

    @Column(name="email")
    private String email;

    @Column(name="senha")
    private String senha;

    @Column(name="matricula", unique=true)
    private String matricula;

    gets... 
    sets...
}

If I set the transaction handled by provider to true

"setTransactionsHandledByProvider(false);", i'll get the error 
" A JTA EntityManager cannot use getTransaction()".

If anybody could point me to a working example or just give me a hint about what I'm doing wrong, would be much appreciated.

Bhavesh Odedra
  • 10,990
  • 12
  • 33
  • 58
  • How `super.runInTransaction(operation) method` look like ? – wypieprz Apr 22 '15 at 20:47
  • Do you have a specific reason to use JPAContainer? For any serious usage I suggest to use a @Stateless EJB to hide the JPA stuff from the UI layer. Then just pass list of your entity objects to UI components with BeanItemContainer. Or if you care a lot a about the performance of your application, check out Viritin add-on and its [lazy loading features](https://vaadin.com/web/matti/blog/-/blogs/more-on-lazy-data-binding). Those perform better than JPAContainer (both CPU and memory) and are easier to use. – mstahv Apr 23 '15 at 06:40
  • @wypieprz, super.runInTransaction(operation) yields the same result... but thanks – Eduardo Ribeiro Apr 23 '15 at 16:46
  • @mstahv, I did think about it, but that would break my whole application, instead i'm controlling the EntityManager manually and passing to the JPAContainer, i know it's not the best thing to do, but it solved the problem and didn't really require a lot of refactoring. – Eduardo Ribeiro Apr 23 '15 at 16:49
  • Not using JPAContainer or using Java EE application server? It should be possible to gradually move from JPAContainer to Facade+BeanItemContainer/Viritin style architecture. EJB would just make the DB access bit easier than with plain EntityManager. – mstahv Apr 23 '15 at 21:38

1 Answers1

0

The following error is self explanatory:

A JTA EntityManager cannot use getTransaction()

In other words you cannot call EntityTransaction.getTransaction() when JTA is specified by the data source in the persistence.xml.


Below are general rules for Transaction Management so you can follow one of them and adopt the provider according to your needs.

  • resource­-local transactions (Java EE / Java SE)

    • application­-managed entity manager

       @PersistenceUnit(unitName="...")
       EntityManagerFactory emf;
      
       public void foo() {
           em.getTransaction.begin(); //explicit begin
           ...
           em.getTransaction.commit(); // explicit commit
       }
      
  • JTA transactions (Java EE only)

    • application­-managed entity manager (bean-­managed transactions)

       @PersistenceUnit(unitName="...")
       EntityManagerFactory emf;
       EntityManager em = emf.createEntityManager();
      
       @Resource
       UserTransaction tx;
      
       public void foo() {
           tx.begin(); //explicit begin
           ...
           tx.commit(); // explicit commit
       }
      
    • container­-managed entity manager via EJB (container­-managed transactions)

        @PersistenceContext(unitName="...")
        EntityManager em;
      
        @TransactionAttribute(TransactionAttributeType.REQUIRED) //default
        public void foo() {
            // implicit begin
            ...
            // implicit commit
        }
      
    • container­-managed entity manager via CDI (container­-managed transactions)

        @PersistenceContext(unitName="...")
        EntityManager em;
      
        @Transactional(TxType.REQUIRED) //default
        public void foo() {
            // implicit begin
            ...
            // implicit commit
        }
      
wypieprz
  • 7,981
  • 4
  • 43
  • 46
  • i get that, but the problem lies in the Vaadin's JPAContainer. The vaadin FieldGroup is trying to persist the entity, it's not my code. – Eduardo Ribeiro May 06 '15 at 21:51
  • I can hardly believe it. Your example looks pretty much the same as Matti Tavhonen's [Using JPA Container 2.0 in a JEE6 server](https://vaadin.com/web/matti/blog/-/blogs/using-jpa-container-2-0-in-a-jee6-server) blog post. Have you tried to inject EntityManager instead of HibernateUtil's assignment and initialize the class as specified in the [reference example](https://dev.vaadin.com/svn/incubator/jpacontainerjee6/src/main/java/org/vaadin/jpacontainerjee/EjbEntityProvider.java) ? – wypieprz May 07 '15 at 22:22