2013-07-24 8 views
6

Ich arbeite an einer Anwendung, die Spring 3, Hibernate und JPA verwendet. Ich habe zwei Klassen wie folgt:Spring Scheduler - Wenn eine zyklische Abhängigkeit besteht, startet die geplante Methode nicht in der Transaktion

@Component 
class Manager { 
    @Autowired 
    Util util; 
} 

und

@Component 
class Util { 
    @Autowired 
    Manager manager; 

    @Scheduled(fixedDelay = 1 * 60 * 1000) 
    @Transactional(propagation = Propagation.REQUIRED) 
    public void scheduledMethod(){ 
     // Need to update the database in a transaction 
    } 
} 

Der relevante Teil von Anwendungskontext ist wie folgt:

<context:component-scan base-package="packageName" /> 
    <tx:annotation-driven /> 
    <bean id="entityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="persistenceUnitName" value="defaultPU" /> 
     <property name="dataSource" ref="dataSource" /> 
    </bean> 
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
     <property name="entityManagerFactory" ref="entityManagerFactory" /> 
    </bean> 
    <task:annotation-driven executor="executor" scheduler="scheduler"/> 
    <task:executor id="executor" 
     pool-size="10" 
     queue-capacity="10000" 
     rejection-policy="CALLER_RUNS"/> 
    <task:scheduler id="scheduler" pool-size="10"/> 

Mit dieser Konfiguration, erhalte ich die folgende Ausnahme

javax.persistence.TransactionRequiredException: no transaction is in progress 
     at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:978) 
     at sun.reflect.GeneratedMethodAccessor88.invoke(Unknown Source) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
     at java.lang.reflect.Method.invoke(Method.java:601) 
     at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365) 
     at com.sun.proxy.$Proxy43.flush(Unknown Source) 
     at sun.reflect.GeneratedMethodAccessor88.invoke(Unknown Source) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
     at java.lang.reflect.Method.invoke(Method.java:601) 
     at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240) 
     at com.sun.proxy.$Proxy43.flush(Unknown Source) 

Wenn ich die Autowirkung der Manager-Klasse aus der Util-Klasse entferne, funktioniert das problemlos. Beim Debugging habe ich festgestellt, dass die geplante Methode gestartet wird, auch wenn ein Fehler in der Anwendungskontextdatei auftritt.

Aus bestimmten Gründen kann ich die zyklische Abhängigkeit nicht vermeiden. Kann jemand helfen, warum diese Ausnahme bei zyklischer Abhängigkeit auftritt?

+0

Es scheint, dass nackte Bohne geplant Nachprozessor Prozesse achive auch wenn es nach dem AOP-Proxy-Schöpfer Feuer angenommen hat (weil Postprozessoren bestellt werden). Ich denke du kannst einen Bug an Spring JIRA senden, zumindest ist dieses Verhalten schlecht dokumentiert. Um dieses Problem zu umgehen, können Sie die Transaktionsmethode von einer separaten Bean mit der geplanten Methode auslösen oder TransactionTemplate statt transactional verwenden. –

Antwort

0

Sie können diese mit @PostConstruct

@Component 
class Manager { 

    Util util; 

    public void setUtil(Util util) { 
     this.util = util; 
    } 
} 


@Component 
class Util { 
    @Autowired 
    Manager manager; 

    @PostConstruct 
    public void init(){ 
     manager.setUtil(this); 

    } 

    @Scheduled(fixedDelay = 1 * 60 * 1000) 
    @Transactional(propagation = Propagation.REQUIRED) 
    public void scheduledMethod(){ 
     // Need to update the database in a transaction 
    } 
}