0

Я переношу существующее приложение командной строки Spring-Batch в webapp, используя spring-boot-starter-web и spring-boot-starter-data-jpa вместе с функцией Spring- batch-admin (версия 1.3.0).Spring-Boot Webapp с несколькими базами данных JTA выбрасывает BeanCreationException

Я попытался настроить приложение так, чтобы он мог работать с несколькими базами данных. После многих попыток и ошибок я наконец последовал за этим примером JTA stackoverflow.com/questions/22779155/.

Но все же я сталкиваюсь с тем же BeanCreationException снова и снова (см. StackTrace в конце сообщения).

Возможно, возникла проблема из-за интеграции с пружинным пакетом-админ?

Вот как ServletInitializer выглядит следующим образом:

@Configuration 
@EnableAutoConfiguration(exclude = { BatchAutoConfiguration.class, 
    DataSourceAutoConfiguration.class, WebMvcAutoConfiguration.class }) 
@Import(MainConfiguration.class) 
public class BatchAdmin extends SpringBootServletInitializer { 
     public static void main(String[] args) { 
      SpringApplication.run(BatchAdmin.class, args); 
     } 
     // ... 
} 

Здесь основным классам конфигурации, как это было предложено в afromentioned SO-статье:

@Configuration 
@ComponentScan("com.company.*") 
@Import({ ServletConfiguration.class, WebappConfiguration.class, Db1Configuration.class, 
    Db2Configuration.class }) 
@EnableTransactionManagement 
public class MainConfiguration { 

    @Bean 
    public JpaVendorAdapter jpaVendorAdapter() { 
    HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter(); 
    hibernateJpaVendorAdapter.setShowSql(true); 
    hibernateJpaVendorAdapter.setGenerateDdl(true); 
    hibernateJpaVendorAdapter.setDatabase(Database.POSTGRESQL); 
    hibernateJpaVendorAdapter.setDatabasePlatform(MyPGDialect.class.getName()); 
    return hibernateJpaVendorAdapter; 
    } 

    @Bean(name = "userTransaction") 
    public UserTransaction userTransaction() throws Throwable { 
    UserTransactionImp userTransactionImp = new UserTransactionImp(); 
    userTransactionImp.setTransactionTimeout(10000); 
    return userTransactionImp; 
    } 

    @Bean(name = "atomikosTransactionManager", initMethod = "init", destroyMethod = "close") 
    public TransactionManager atomikosTransactionManager() throws Throwable { 
    UserTransactionManager userTransactionManager = new UserTransactionManager(); 
    userTransactionManager.setForceShutdown(false); 
    return userTransactionManager; 
    } 

    @Bean(name = "transactionManager") 
    @DependsOn({ "userTransaction", "atomikosTransactionManager" }) 
    public PlatformTransactionManager transactionManager() throws Throwable { 
    UserTransaction userTransaction = userTransaction(); 
    TransactionManager atomikosTransactionManager = atomikosTransactionManager(); 
    return new JtaTransactionManager(userTransaction, atomikosTransactionManager); 
    } 
} 

И для каждой базы данных, это собственный класс конфигурации :

@Configuration 
@EnableTransactionManagement 
@EnableJpaRepositories(
    entityManagerFactoryRef = "entityManagerFactory1", 
    transactionManagerRef = "transactionManager", 
    basePackages = { "com.company.model.repository" }) 
@DependsOn("transactionManager") 
public class Db1Configuration { 

    @Autowired 
    private JpaVendorAdapter jpaVendorAdapter; 

    @Bean(name = "dataSource1", initMethod = "init", destroyMethod = "close") 
    public DataSource osmDataSource() { 
    PGXADataSource pgDataSource = new PGXADataSource(); 
    pgDataSource.setServerName("localhost"); 
    pgDataSource.setDatabaseName("db1"); 
    pgDataSource.setPortNumber(5432); 
    pgDataSource.setUser("postgres"); 
    pgDataSource.setPassword("postgres"); 

    AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean(); 
    xaDataSource.setXaDataSource(pgDataSource); 
    xaDataSource.setUniqueResourceName("datasource1"); 
    return xaDataSource; 
    } 

    @Bean(name = "entityManagerFactory1") 
    public LocalContainerEntityManagerFactoryBean customerEntityManager() throws Throwable { 
    LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean(); 
    entityManager.setDataSource(osmDataSource()); 
    entityManager.setJpaVendorAdapter(jpaVendorAdapter); 
    entityManager.setPackagesToScan("com.company.model.domain"); 
    entityManager.setPersistenceUnitName("persistenceUnit1"); 
    HashMap<String, Object> properties = new HashMap<String, Object>(); 
    properties.put("hibernate.transaction.jta.platform", AtomikosJtaPlatform.class.getName()); 
    // properties.put("javax.persistence.transactionType", "JTA"); 
    properties.put("hibernate.hbm2ddl.auto", ""); 
    entityManager.setJpaPropertyMap(properties); 
    return entityManager; 
    } 
} 

Это то, что дает мне его доходит до:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class]: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.requestMappingHandlerMapping()] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'openEntityManagerInViewInterceptor' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration$JpaWebConfiguration.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined: expected single matching bean but found 2: osm.entityManagerFactory,entityManagerFactory 
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:597) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1094) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:989) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482) 
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:120) 
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:320) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:952) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:941) 
    at com.qompa.batch.admin.BatchAdmin.main(BatchAdmin.java:58) 
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.requestMappingHandlerMapping()] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'openEntityManagerInViewInterceptor' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration$JpaWebConfiguration.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined: expected single matching bean but found 2: osm.entityManagerFactory,entityManagerFactory 
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:188) 
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:586) 
    ... 17 more 
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'openEntityManagerInViewInterceptor' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration$JpaWebConfiguration.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined: expected single matching bean but found 2: osm.entityManagerFactory,entityManagerFactory 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:547) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) 
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:324) 
    at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration$JpaWebConfiguration$$EnhancerBySpringCGLIB$$e9895182.openEntityManagerInViewInterceptor(<generated>) 
    at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration$JpaWebConfiguration.addInterceptors(JpaBaseConfiguration.java:144) 
    at org.springframework.web.servlet.config.annotation.WebMvcConfigurerComposite.addInterceptors(WebMvcConfigurerComposite.java:105) 
    at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration.addInterceptors(DelegatingWebMvcConfiguration.java:55) 
    at org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.getInterceptors(WebMvcConfigurationSupport.java:226) 
    at org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.requestMappingHandlerMapping(WebMvcConfigurationSupport.java:198) 
    at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerBySpringCGLIB$$216f202d.CGLIB$requestMappingHandlerMapping$17(<generated>) 
    at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerBySpringCGLIB$$216f202d$$FastClassBySpringCGLIB$$7252bcc7.invoke(<generated>) 
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) 
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:312) 
    at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerBySpringCGLIB$$216f202d.requestMappingHandlerMapping(<generated>) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:166) 
    ... 18 more 
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined: expected single matching bean but found 2: osm.entityManagerFactory,entityManagerFactory 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:313) 
    at org.springframework.orm.jpa.EntityManagerFactoryUtils.findEntityManagerFactory(EntityManagerFactoryUtils.java:142) 
    at org.springframework.orm.jpa.EntityManagerFactoryAccessor.setBeanFactory(EntityManagerFactoryAccessor.java:137) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1572) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1540) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539) 
    ... 40 more 

Любые идеи отсутствуют?

ответ

5

Если у всех ваших dao нет @Qualifier, чтобы указать, какой EntityManager использовать, вам придется помечать один из этих EntityManagerFactory с помощью @Primary.

@Bean(name = "entityManagerFactory1") 
    @Primary 
    public LocalContainerEntityManagerFactoryBean ... 

Скорее всего, вам придется сделать то же самое для своего источника данных.

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