javax.persistence.TransactionRequiredException: no transaction is in progress

Denis

Grünschnabel
Hallo,

ich experimentiere in den letzten Wochen mit EJB (3.1), Spring (2.5) und Glassfish (3.1) und bin auf ein Problem mit der Transaktionsverwaltung gestoßen.
Vielleicht fällt Euch der Fehler auf. Ich finde Ihn definitiv nicht.


Service :
Code:
public void saveNamespace() {
TransactionTemplate transactionTemplate = (TransactionTemplate) appContext.getBean("txTemplate");
  try {
    transactionTemplate.execute(new TransactionCallback() {
      public Object doInTransaction(TransactionStatus status) {
        ApplicationDao dao = factory.createApplicationDao();

        try {
          Namespace namespace = factory.createNamespace("test1");
          namespace.setDescription("test1");
          dao.saveNamespace(namespace); 
						
        } catch (Throwable ex) {
          status.setRollbackOnly();
        }
    }
  });
}

Dao :
Code:
@Repository
public class ApplicationDaoImpl /*extends JpaDaoSupport*/ implements ApplicationDao {
  @PersistenceContext  //Injiziert EntityManager
  private EntityManager entityManager;

  public void saveNamespace(Namespace namespace) {
    getEntityManager().merge((NamespaceImpl) namespace);
  }
	
  ...
}


Model :
Namespace --> NamespaceImpl


Spring - config :
Code:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:flow="http://www.springframework.org/schema/webflow-config"
       xmlns:jms="http://www.springframework.org/schema/jms"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:lang="http://www.springframework.org/schema/lang"
       xmlns:osgi="http://www.springframework.org/schema/osgi"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
       http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/webflow-config/spring-webflow-config-1.0.xsd
       http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-2.5.xsd
       http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
       http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd
       http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">

    <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

    <bean
        class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" >
        <property name="defaultPersistenceUnitName" value="test_db"/>
    </bean>

    <jee:jndi-lookup id="dataSource" jndi-name="test_db"/>

    <bean id="entityManagerFactory"
          class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="database" value="POSTGRESQL" />
                <property name="generateDdl" value="false" />
                <property name="showSql" value="true" />
            </bean>
        </property>
        <property name="persistenceUnitName" value="test_db" />
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    <bean id="txTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="transactionManager"/>
    </bean>

 ...
</beans>


persistence.xml :
Code:
<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_1_0.xsd"
             version="1.0">

	<persistence-unit name="test_db">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>

        <class>test.NamespaceImpl</class>

        <properties>
            <property name="hibernate.archive.autodetection" value=""/>

            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="use_sql_comments" value="true"/>

            <property name="hibernate.connection.useUnicode" value="true" />
            <property name="hibernate.connection.charSet" value="UTF-8" />
            <property name="hibernate.connection.characterEncoding" value="UTF-8" />
            <property name="hibernate.max_fetch_depth" value="3"/>

            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
            <property name="hibernate.cache.use_query_cache" value="true" />
            <property name="hibernate.cache.provider_class" value="org.hibernate.cache.EhCacheProvider" />
            <property name="hibernate.cache.provider_configuration_file_resource_path" value="/ehcache-master.xml" />
        </properties>
    </persistence-unit>
</persistence>


Glassfish - domain.xml :
In Glassfish habe ich einen jdbc connection pool eingerichtet.

Code:
<resources>
<jdbc-connection-pool driver-classname="org.postgresql.Driver" res-type="java.sql.Driver" name="test_db" transaction-isolation-level="read-committed">
  <property name="URL" value="jdbc:postgresql://localhost/test_db" />
  <property name="password" value="admin" />
  <property name="user" value="admin" />
</jdbc-connection-pool>
<jdbc-resource pool-name="test_db" jndi-name="test_db" />
</resources>


Fehlermeldung :
Das Lesen von Daten aus der Datenbank funktioniert (anscheinend nicht in der von mir veranlassten Transaktion)
Ein schreibender Zugriff führt zu dieser Exception :
Code:
[#|2010-04-15T21:43:55.618+0200|INFO|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=30;_ThreadName=Thread-1;|javax.persistence.TransactionRequiredException: no transaction is in progress
	at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:294)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:346)
	at $Proxy200.flush(Unknown Source)


Wisst Ihr, wo der Fehler verborgen ist ?
Ich gehe stark davon aus, dass die spring config und/oder die persistence.xml fehlerhaft ist.
Mir ist auch noch nicht klar, wer auf den injizierten EntityManager ein close aufruft, und die Resourcen freigibt ? Wird dies automatisch freigegeben, sobald die Dao Klasse nicht
mehr referenziert wird ?

Ihr würdet mir sehr helfen, wenn Ihr mir bei dem Problem helfen könntet.

Grüße
Denis
 
Zuletzt bearbeitet:
Hi Denis,

genau kann ich es Dir auf die Schnelle nicht beantworten. Was ich jedoch an Deiner Stelle versuchen würde ist folgendes:

Du hast bereits in deinem ApplicationContext.xml die Bean PersistenceAnnotationBeanPostProcessor erzeugt sowie einen tx-Manager. Versuch doch mal deine Configuration durch folgendes zu erweitern:

Definiere das die Transaction Annotation-Driven ist:

Code:
<tx:annotation-driven />

Evtl. musst du nebst der aktivierung der Annotation-Driven Transaction noch den spezifischen Transactionsmanager (JPA oder welchen Du auch nutzt) deklarieren:

Code:
transaction-manager="transactionManager"

Danach musst Du noch das entsprechende DAO oder Service mit der Annotation @Transactional kennzeichnen. Somit solltest Du neu eine Transaction haben - zumindest aus sicht JPA und Spring.

Evtl. hilft Dir diese info einwenig weiter.

cheers

lumpiscore
 
Mal eine blöde Frage...Warum machst Du die Transaktionsmangerklamotte händisch?

Eine Transaktionsklammer erreichst Du doch bei Java EE durch @Transaction.RequiresNew. Warum lässt Du Deinen Container nicht die Transaktionen verwalten?

[EDIT] ich schalte autocommit bei Postgresql explizit auf false. Das könnte schon die Lösung Deines Rätsels sein.

Ausserdem verwende ich in EJB3.x Anwendungen kein Spring (wozu auch?). Da Du hier mit Spring-Transaktionsmanagement agierst, weiss ich nicht, wie gut oder schlecht sich das mit dem Container verträgt.

[/EDIT]

Grüße
gore
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück