2014-09-05 3 views
1

Я переношу свои весенние пакетные процессы из приложения командной строки в веб-приложение весной загрузки, включая диспетчер spring-batch-admin-manager (версия 1.3.0).Весна не может выбирать между несколькими бобами TransactionManager

Мое старое приложение с командной строкой работало с двумя базами данных JPA и двумя экземплярами TransactionManager. Я помню, что это была адская конфигурация, чтобы добиться этого. Я ожидал, что что-то станет более комфортным, начиная с Spring Boot, но теперь ситуация выглядит еще хуже:

Spring не может выбрать правильный экземпляр TransactionManager для транзакций.

При запуске приложения Spring посещает один из моих классов, чтобы выполнить блок аннотированных кодов @PostConstruct, откуда должен быть вызван метод транзакции.

@PostConstruct 
public void init() { 
    eventType = eventTypeBo.findByLabel("Sport"); // <-- Calling transactional method 
    //... 
} 

Отсюда ошибка. Посмотрите на StackTrace:

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
      No qualifying bean of type [org.springframework.transaction.PlatformTransactionManager] is defined: 
      expected single matching bean but found 2: transactionManager,osm.transactionManager 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:313) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.determineTransactionManager(TransactionAspectSupport.java:337) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:252) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) 
    at com.sun.proxy.$Proxy89.findByLabel(Unknown Source) 
    at com.company.model.service.impl.EventTypeBo.findByLabel(EventTypeBo.java:43) 
    at com.company.batch.article.utils.converter.SomeConverter.init(SomeConverter.java:83) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    //... 

Как вы можете видеть журнал ошибок, мои TransactionManager s называются «TransactionManager» и «osm.transactionManager». Операции выполнены соответственно:

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

<!-- DATABASE 2 --> 
<bean id="osm.transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="osm.entityManagerFactory" /> 
</bean> 
<tx:advice id="txAdvice" transaction-manager="osm.transactionManager"> 
    <tx:attributes> 
     <tx:method name="*" /> 
    </tx:attributes> 
</tx:advice> 
<aop:config> 
    <aop:pointcut id="osmServiceOperation" 
     expression="execution(* com.qompa.osm.service.spec..*Service.*(..))" /> 
    <aop:advisor advice-ref="txAdvice" pointcut-ref="osmServiceOperation" /> 
</aop:config> 

Я использую два различных implementions GenericDao различать PersistenceContext с при доступе к данным:

public class OsmGenericDao<T> implements IGenericDao<T> { 

    @PersistenceContext(unitName = "osm.entityManagerFactory") 
    protected EntityManager em; 
    //... 
} 

public class GenericDao<T> implements IGenericDao<T> { 

    @PersistenceContext(unitName = "entityManagerFactory") 
    protected EntityManager em; 
    //... 
} 

Все, кажется, fproperly настроен: Но все-таки не удается!

EDIT: Насколько я могу следовать в Spring TransactionAspectSuppor т пытается определить TransactionManager через классификатор (determineTransactionManager). Поскольку @Transactional аннотаций в findByLabel не имеет никакого спецификатора он пытается определить правильный компонент с помощью getBean метода DefaultListableBeanFactory «ю.ш., где находятся два зерна одного и того же типа, что не может быть далее выделено.

Там должны быть способ сказать Spring выбрать TransactionManager в соответствии с контекстом инерционности

Любые идеи

+1

Ditch '' и '' и удалите 'transaction-manager =" transactionManager "' из ''.Вместо этого используйте '@ Transactional' всюду и укажите, какой диспетчер транзакций будет использовать на нем те' @ Transactional'. –

+1

Я нашел это уродливое решение, потому что я привязываю свои модули к определенному имени TransactionManager. Он работал раньше, так что теперь ... должен быть другой путь! – achingfingers

+0

Итак, вы не против привязывать его к определенному сущ., Но проблема с tx-маназером? С '@ Transactional' вам нужно указать, что использовать, в случае нескольких менеджеров. Если вы не используете несколько '' bllocks. –

ответ

1

Вот моя рабочая конфигурация с 2 настойчивостью контекстах:?

<!-- METADATA --> 

<!-- Metadata connection pool --> 
<bean id="scprMetadataDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" 
    destroy-method="close"> 
    <property name="driverClass" 
     value="..." /> 
    <property name="jdbcUrl" 
     value="..." /> 
    <property name="user" 
     value="..." /> 
    <property name="password" 
     value="..." /> 
    <property name="maxPoolSize" 
     value="..." /> 
    <property name="minPoolSize" 
     value="..." /> 
</bean> 

<!-- Metadata entity manager factory --> 
<bean id="scprMetadataEntityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="jpaVendorAdapter"> 
     <bean 
      class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter"> 
      <property name="database" value="H2" /> 
     </bean> 
    </property> 
</bean> 

<!-- Metadata transaction manager --> 
<bean id="scprMetadataTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="scprMetadataEntityManagerFactory" /> 
</bean> 


<!-- DOMAIN --> 

<!-- Domain connection pool --> 
<bean id="scprDomainDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" 
    destroy-method="close"> 
    <property name="driverClass" 
     value="..." /> 
    <property name="jdbcUrl" 
     value="..." /> 
    <property name="user" 
     value="..." /> 
    <property name="password" 
     value="..." /> 
    <property name="maxPoolSize" 
     value="..." /> 
    <property name="minPoolSize" 
     value="..." /> 
</bean> 

<!-- Domain entity manager factory --> 
<bean id="scprDomainEntityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="jpaVendorAdapter"> 
     <bean 
      class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter"> 
      <property name="database" value="SQL_SERVER" /> 
     </bean> 
    </property> 
</bean> 

<!-- Domain transaction manager --> 
<bean id="scprDomainTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="scprDomainEntityManagerFactory" /> 
</bean> 

Другие конфигурации (отсутствует в вашем вопросе):

<persistence-unit name="scpr_metadata" transaction-type="RESOURCE_LOCAL"> 
    <exclude-unlisted-classes>true</exclude-unlisted-classes> 
    <class>...</class> 
    <class>...</class> 
    <class>...</class> 
</persistence-unit> 

<persistence-unit name="scpr_domain" transaction-type="RESOURCE_LOCAL"> 
    <exclude-unlisted-classes>true</exclude-unlisted-classes> 
    <class>...</class> 
    <class>...</class> 
    <class>...</class> 
</persistence-unit> 

И в моем Java классе:

@Repository 
public final class MetadataRepositoryImpl implements MetadataRepository { 

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

И:

@Repository 
public final class DomainRepositoryImpl implements DomainRepository { 

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

Надеется, что это помогает.

+0

Это именно то, что я делал. Просто опустил persistence.xml в моем вопросе. Та же конфигурация, с которой я сейчас работаю, запущена и запущена в приложении командной строки. Вот почему я думаю, что это может быть проблема с конфигурацией весны ... Спасибо, в любом случае! – achingfingers

Смежные вопросы