# Spring-Transaktion wird nicht gestartet per Annotation ("no transaction is in progress")



## thomasvonkapellen (7. Sep 2011)

Hallo,

ich schreibe eine Webanwendung mit JavaServerFaces/Spring/Hibernate-Jpa auf einem Glassfish-Server (3.1.1), die auf eine MySql Datenbank zugreift. Die Anwendung hat einen Präsentationslayer, einen Servicelayer und einen Datenlayer (hübsch wie im Lehrbuch beschrieben). Transaktionen sollen in der Serviceschicht mit Hilfe von Spring verarbeitet werden. Das Problem ist, dass bei Verwendung der @Transactional-Annotation in der Serviceschicht die Transaction nicht gestartet/ausgeführt wird. Es kommt zu folgendem Fehler bei merge bzw. persist:


```
INFO: no transaction is in progress
INFO: class javax.persistence.TransactionRequiredException
```

Das Merkwürdige ist, dass sobald ich die @Transactional-Annotation in der Datenschicht (DAO) verwende, wird die Transaktion korrekt ausgeführt. ???:L

Hier meine Konfiguration/Quelltext:

1. persistence.xml


```
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" 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">
  <persistence-unit name="WebSpringPU">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <properties>
      <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
      <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/infosys12"/>
      <property name="hibernate.connection.username" value="service"/>
      <property name="hibernate.connection.password" value="123456"/>
      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
      
    </properties>
  </persistence-unit>
</persistence>
```

2. spring-config.xml

```
<?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:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
            [url=http://www.springframework.org/schema/beans]Index of /schema/beans[/url]
            [url]http://www.springframework.org/schema/beans/spring-beans-3.0.xsd[/url]
            [url=http://www.springframework.org/schema/tx]Index of /schema/tx[/url]
            [url]http://www.springframework.org/schema/tx/spring-tx-3.0.xsd[/url]
            [url=http://www.springframework.org/schema/aop]Index of /schema/aop[/url]
            [url]http://www.springframework.org/schema/aop/spring-aop-3.0.xsd[/url]
            [url=http://www.springframework.org/schema/context]Index of /schema/context[/url]
            http://www.springframework.org/schema/context/spring-context-3.0.xsd">
   
   
    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="WebSpringPU" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="false" />
                <property name="generateDdl" value="false" />
                <property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
            </bean>
        </property>
    </bean>    
    
    <context:component-scan base-package="gui" />
    <context:component-scan base-package="dao" />
    <context:component-scan base-package="service" />
    <context:component-scan base-package="service.impl" />
 
    <context:annotation-config />
    <tx:annotation-driven />

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
        <!--<property name="dataSource" ref="dataSource"/>-->
    </bean>
    
    <tx:annotation-driven transaction-manager="transactionManager"/>    

    <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
        <property name="scopes">
            <map>
                <entry key="view">
                    <bean class="spring.ViewScope"/>
                </entry>
            </map>
        </property>
    </bean>

</beans>
```

3. LaenderDaoJpa.java


```
package dao.jpa;

import dao.LaenderDao;
import domain.Laender;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Named;
import javax.inject.Singleton;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.springframework.transaction.annotation.Transactional;

@Named("laenderDao")
@Singleton
public class LaenderDaoJpa implements LaenderDao {

   @PersistenceContext(unitName="WebSpringPU")
   private EntityManager em;

    @Override 
    // @Transactional // this works!
    public void save(Laender land) {
        System.out.println("About to persist/merge...");
        if (land.getId() != null) {
          em.merge(land);
          System.out.println("merged!");
        } else {
         em.persist(land);
         System.out.println("persisted!");
        }
        em.flush();
        System.out.println("OK!");
    }

    @Override
    // @Transactional // this works!
    public Laender read() {
        Laender result = null;
        Query qry;
        qry = em.createNamedQuery("Laender.findById");
        qry.setParameter("param", 1);
        result = (Laender) qry.getSingleResult();
        return result;

    }
}
```

4. LaenderServiceImpl.java

```
package service.impl;

import dao.LaenderDao;
import domain.Laender;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import service.LaenderService;

@Named("laenderService")
@Singleton
public class LaenderServiceImpl implements LaenderService {
    
    @Inject
    LaenderDao laenderDao;

    @Override
    @Transactional // this doesn't work
    public void save(Laender land) {
        laenderDao.save(land);
    }

    @Override
    @Transactional // this doesn't work
    public Laender read() {
        return laenderDao.read();
    }
}
```


5. Page1.java

```
package gui;

import dao.LaenderDao;
import domain.Laender;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.inject.Named;
import org.springframework.context.annotation.Scope;

@Named
@Scope("view")
public class Page1 implements Serializable {

    private String value;
    private Laender land;

    @Inject
    LaenderDao laenderService;

    @PostConstruct
    public void construct() {
        System.out.println("************* contruct " + this.getClass().getName());
        value = "Wert von Page 1";
        try {

            System.out.println("Read from db...");
            land=laenderService.read();
            System.out.println("Old value: \""+land+"\"");

            System.out.println("Change value...");
            land.setBezeichnung("Deutschland123");
            laenderService.save(land);

        } catch (Exception ex) {
            System.out.print("ERROR: ");
            System.out.println(ex.getMessage());
            System.out.println(ex.getClass() );
            System.out.println(ex.getCause()); 
        }

    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public Laender getLand() {
        return land;
    }

    public void setLand(Laender land) {
        this.land = land;
    }
}
```


Es ist mein erstes Spring-Projekt und ich versuche jetzt schon seit Tagen die Transktionssteuerung in den Griff zu bekommen, leider ohne Erfolg.

Spring verwende ich in der Version 3.0.2. und da Transaktionen prinzipiell zu funktionieren scheinen, gehe ich davon aus, dass meine Konfiguration nicht völlig falsch ist.

Ich hoffe jemand hat eine Idee, die mir weiterhilft. Im Anhang findet Ihr noch das komplette (Netbeans) Projekt.


----------



## Noctarius (7. Sep 2011)

Wieso hast du 2x [c]<tx:annotation-driven .../>[/c]?

Theoretisch sollte das zweite reichen


----------



## thomasvonkapellen (8. Sep 2011)

Danke, du hast vollkommen recht, den 1. Eintrag habe ich entfernt. Das löst mein Problem leider nicht, Transaktion funktioniert in der DAO aber nicht im Service.


----------



## Noctarius (8. Sep 2011)

Hm spontan ne Idee habe ich auch nicht wirklich. Schon mal versucht die Service Implementierung mit @Service zu annotieren?


----------



## thomasvonkapellen (8. Sep 2011)

Ok, manchal gehört man geschlagen, man sollte den Service auch als Service und nicht als DAO definieren. Seltsame Fehler verursachen seltsame Reaktionen :noe:

Fehler:

```
@Inject
LaenderDao laenderService;
```

Geändert in...

```
@Inject
LaenderService laenderService;
```

Alles prima, danke.


----------



## Noctarius (8. Sep 2011)

Ah huch hab ich aber auch nicht gesehen


----------

