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:
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
2. spring-config.xml
3. LaenderDaoJpa.java
4. LaenderServiceImpl.java
5. Page1.java
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.
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:
Java:
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
Java:
<?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
Java:
<?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
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
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
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.