vendredi 31 juillet 2015

Spring Data autowiring multiple datasources fails

I have been hacking away at trying to get multiple mysql datasources into a Spring jpa application for what seems like forever. I have yet to find a good, working example online. Below are exceprts from an extremely stripped down app I'm making just to see if it is even possible in a vacuum to be able to autowire and query repositories for more than one MySQL db. No matter what annotations I sub in or out nothing changes, I always get the same error:

Error creating bean with name 'application': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.download.integration.repository.primary.PrimaryRepository com.download.Application.PrimaryRepository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.download.integration.repository.primary.PrimaryRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Here is my setup. Primary and Secondary beans and repos are in their own packages per the advice of several previously answered items.

first config:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "primaryEntityManagerFactory",
        transactionManagerRef = "primaryTransactionManager",
        basePackages = { "com.download.integration.repositories.primary" })
public class PrimaryConfig{

    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {
        HibernateJpaVendorAdapter adaptor = new HibernateJpaVendorAdapter();
        adaptor.setShowSql(false);
        adaptor.setGenerateDdl(false);
        adaptor.setDatabase(Database.MYSQL);
        return adaptor;
    }


    @Primary
    @Bean(name = "primaryDataSource")
    public DataSource primaryDataSource() {
        BasicDataSource ds = new BasicDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://127.0.0.1:3306/primarydb");
        ds.setUsername("user");
        ds.setPassword("password");
        return ds;
    }

        @Bean(name = "primaryEntityManager")
        public EntityManager entityManager() {
                return primaryEntityManagerFactory().createEntityManager();
        }

        @Bean(name = "primaryEntityManagerFactory")
        public EntityManagerFactory primaryEntityManagerFactory() {
                LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
                lef.setDataSource(primaryDataSource());
                lef.setJpaVendorAdapter(jpaVendorAdapter());
                lef.setPackagesToScan("com,download.domain.primary");
                lef.setPersistenceUnitName("primaryPersistenceUnit");
                lef.afterPropertiesSet();
                return lef.getObject();
        }

        @Bean(name = "primaryTransactionManager")
        public PlatformTransactionManager primaryTransactionManager() {
                return new JpaTransactionManager(primaryEntityManagerFactory());
        }

}

secondary config:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "secondaryEntityManagerFactory",
        transactionManagerRef = "secondaryTransactionManager",
        basePackages = { "com.download.integration.repositories.secondary" })
public class SecondaryConfig{

    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {
        HibernateJpaVendorAdapter adaptor = new HibernateJpaVendorAdapter();
        adaptor.setShowSql(false);
        adaptor.setGenerateDdl(false);
        adaptor.setDatabase(Database.MYSQL);
        return adaptor;
    }

    @Bean(name = "secondaryDataSource")
    public DataSource secondaryDataSource() {
        BasicDataSource ds = new BasicDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://127.0.0.1:3306/secondarydb");
        ds.setUsername("user");
        ds.setPassword("password");
        return ds;
    }

        @Bean(name = "secondaryEntityManager")
        public EntityManager entityManager() {
                return secondaryEntityManagerFactory().createEntityManager();
        }

        @Bean(name = "secondaryEntityManagerFactory")
        public EntityManagerFactory secondaryEntityManagerFactory() {
                LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
                lef.setDataSource(secondaryDataSource());
                lef.setJpaVendorAdapter(jpaVendorAdapter());
                lef.setPackagesToScan("com,download.domain.secondary");
                lef.setPersistenceUnitName("secondaryPersistenceUnit");
                lef.afterPropertiesSet();
                return lef.getObject();
        }

        @Bean(name = "secondaryTransactionManager")
        public PlatformTransactionManager secondaryTransactionManager() {
                return new JpaTransactionManager(secondaryEntityManagerFactory());
        }

}

primary datasource model:

@Entity
public class Primary {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    private String word;
    private Double weight;
    private Date updated;
    private String sources;

...constructors, getters, setters

secondary datasource model:

@Entity
public class Secondary {

    @Id
    private String uuid;
    private String name;
    private Double weight;

...constructors, getters, setters

And repositories (I have experiments with adding @Repository and seen no change)

public interface Primary extends CrudRepository<Primary, Integer> {
}

public interface Secondary extends CrudRepository<Secondary, Integer> {
}

finally, the main class:

@ComponentScan("com.download")
@EnableAutoConfiguration(exclude = { DataSourceTransactionManagerAutoConfiguration.class, DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
@Import({PrimaryConfig.class, SecondaryConfig.class})
public class Application implements CommandLineRunner{

    @Autowired
    PrimaryRepository primaryrepository;
    @Autowired
    SecondaryRepository secondaryrepository;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void run(String... args) throws Exception {

        search();

    }

    public void search(){
        primaryrepository.findAll();
        secondaryrepository.findAll();
    }

}

Aucun commentaire:

Enregistrer un commentaire