title: Spring Boot with multiple datasources and external configuration, Spring JPA
body: <p>i have a simple Spring Boot application with 2 external jars. Each jar uses Spring JPA and is completely configured to work standalone. </p>
  
  <p><strong>Jar1</strong> </p>
  
  <p>JPA Repository</p>
  
  <pre><code>@Repository
  public interface QuarterRepository extends JpaRepository&lt;Quarter, Long&gt;{
  
  
  }
  </code></pre>
  
  <p><strong>Entity</strong></p>
  
  <pre><code>@Entity
  public class Quarter implements Serializable {
      @Id
      @GeneratedValue(strategy = GenerationType.AUTO)
      private Long id;...
  </code></pre>
  
  <p><strong>Configurations</strong></p>
  
  <pre><code>@Configuration
  @Import({RepositoryConfig.class})
  public class OnlineJpaAppConfig{
  
      @Bean(name = "onlinejpaAppConfigConfigurer")
      public static PropertyPlaceholderConfigurer getPropertyPlaceholderConfigurer()    {        
          PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
          ppc.setLocation(new ClassPathResource("/de/comp/onlinejpa/application.properties"));
          ppc.setIgnoreUnresolvablePlaceholders(true);
          return ppc;
      }
  }  
  
  
  @Configuration
  @EnableJpaRepositories(basePackages = {"de.comp.onlinejpa.repository"},
          entityManagerFactoryRef = "onlinejpaentityManagerFactory",
          transactionManagerRef = "onlinejpaTransactionManager")
  @EnableTransactionManagement
  public class RepositoryConfig {
  
      @Value("${jdbc.driverClassName}")
      private String driverClassName;
      @Value("${jdbc.url}")
      private String url;
      @Value("${jdbc.username}")
      private String username;
      @Value("${jdbc.password}")
      private String password;
  
      @Value("${hibernate.dialect}")
      private String hibernateDialect;
      @Value("${hibernate.show_sql}")
      private String hibernateShowSql;
      @Value("${hibernate.hbm2ddl.auto}")
      private String hibernateHbm2ddlAuto;
  
      private static final String QUALIFIER = "onlinejpa";
  
      @Bean(name = "onlinejpaentityManagerFactory")
      public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
          LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
          em.setDataSource(dataSource());
          em.setPackagesToScan(new String[]{"de.comp.onlinejpa.entity"});
          em.setPersistenceUnitName("onlinejpa");
          JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
          em.setJpaVendorAdapter(vendorAdapter);
          em.setJpaProperties(additionalProperties());
  
          return em;
      }
  
      @Bean(name = "onlinejpaDataSource")
      public DataSource dataSource() {
          DriverManagerDataSource dataSource = new DriverManagerDataSource();
          dataSource.setDriverClassName(driverClassName);
          dataSource.setUrl(url);
          dataSource.setUsername(username);
          dataSource.setPassword(password);
          return dataSource;
      }
  
      @Bean(name = "onlinejpaTransactionManager")
      public PlatformTransactionManager transactionManager(@Qualifier(value = "onlinejpaentityManagerFactory") EntityManagerFactory onlinejpaentityManagerFactory) {
          JpaTransactionManager transactionManager = new JpaTransactionManager();
          transactionManager.setEntityManagerFactory(onlinejpaentityManagerFactory);
  
          return transactionManager;
      }
  
      @Bean(name = "onlinejpaExceptionTranslation")
      public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
          return new PersistenceExceptionTranslationPostProcessor();
      }
  
      Properties additionalProperties() {
  
          Properties properties = new Properties();
          properties.setProperty("hibernate.hbm2ddl.auto", hibernateHbm2ddlAuto);
          properties.setProperty("hibernate.dialect", hibernateDialect);
          return properties;
      }
  }
  </code></pre>
  
  <p>The second jar looks almost the same as Jar1, except the bean and the package names</p>
  
  <pre><code>@EnableJpaRepositories(basePackages = {"de.comp.aisjpa.repository"}, 
          entityManagerFactoryRef = "aisjpaentityManagerFactory",
          transactionManagerRef = "aisjpatransactionManager")
  @EnableTransactionManagement
  public class RepositoryConfig {
  
      @Value("${jdbc.driverClassName}")
      private String driverClassName;
      @Value("${jdbc.url}")
      private String url;
      @Value("${jdbc.username}")
      private String username;
      @Value("${jdbc.password}")
      private String password;
  
      @Value("${hibernate.dialect}")
      private String hibernateDialect;
      @Value("${hibernate.show_sql}")
      private String hibernateShowSql;
      @Value("${hibernate.hbm2ddl.auto}")
      private String hibernateHbm2ddlAuto;
  
       private static final String QUALIFIER = "aisjpa";
  
  
      @Bean(name = "aisjpaentityManagerFactory")
      public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
          LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
          em.setDataSource(aisdataSource());
          em.setPackagesToScan(new String[]{"de.comp.aisjpa.entity"});
          em.setPersistenceUnitName("ais");
          JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
          em.setJpaVendorAdapter(vendorAdapter);
          em.setJpaProperties(additionalProperties());
  
          return em;
      }
  
  
  
      @Bean(name = "aisjpadatasource")
      public DataSource aisdataSource() {
          DriverManagerDataSource dataSource = new DriverManagerDataSource();
          dataSource.setDriverClassName(driverClassName);
          dataSource.setUrl(url);
          dataSource.setUsername(username);
          dataSource.setPassword(password);
          return dataSource;
      }
  
  
      @Bean(name = "aisjpatransactionManager")
      public PlatformTransactionManager transactionManager(@Qualifier(value = "aisjpaentityManagerFactory") EntityManagerFactory aisjpaentityManagerFactory) {
          JpaTransactionManager transactionManager = new JpaTransactionManager();
          transactionManager.setEntityManagerFactory(aisjpaentityManagerFactory);
  
          return transactionManager;
      }
  
  
      @Bean(name = "aisjpaexceptionTranslation")
      public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
          return new PersistenceExceptionTranslationPostProcessor();
      }
  
      Properties additionalProperties() {
          Properties properties = new Properties();
          properties.setProperty("hibernate.hbm2ddl.auto", hibernateHbm2ddlAuto);
          properties.setProperty("hibernate.dialect", hibernateDialect);
          return properties;
      }
  }
  </code></pre>
  
  <p>Running this Main class in Jar1 gives the expected results.. ( The same as for Jar2)</p>
  
  <pre><code>public class App {
  
      public static void main(String[] args) {
  
          AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(OnlineJpaAppConfig.class);
  
          QuarterRepository quarterRepository = ctx.getBean("quarterRepository", QuarterRepository.class);
  
          List&lt;Quarter&gt; quarters = quarterRepository.findAll();
  
          for (Quarter quarter : quarters) {
  
              System.out.println(quarter.getQuarter());
  
          }
      }
  }
  </code></pre>
  
  <p>This is the startup class of my Spring Boot application</p>
  
  <pre><code>@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class,
          HibernateJpaAutoConfiguration.class,
          DataSourceTransactionManagerAutoConfiguration.class } )
  @Import({ KVLdapAppConfig.class, OnlineJpaAppConfig.class,AISAppConfig.class})
  
  public class ServerApplication {
  
      public static void main(String[] args) {
  
          SpringApplication.run(ServerApplication.class, args);
      }
  
  }
  </code></pre>
  
  <p>The server is starting without problems, but there are some problems during configuring the jpa stuff. The configuration for persistence unit ais should use an Oracle dialect and driver. It seems that it picks up the configuration of <strong>Jar1</strong>. </p>
  
  <pre><code>Building JPA container EntityManagerFactory for persistence unit 'onlinejpa'
  HCANN000001: Hibernate Commons Annotations {4.0.1.Final}
  HHH000412: Hibernate Core {4.2.0.Final}
  HHH000206: hibernate.properties not found
  HHH000021: Bytecode provider name : javassist
  HHH000204: Processing PersistenceUnitInfo [
  
  
  HHH000130: Instantiating explicit connection provider: org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider
  HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
  HHH000268: Transaction strategy: org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory
  HHH000397: Using ASTQueryTranslatorFactory
  Loaded JDBC driver: com.mysql.jdbc.Driver
  Building JPA container EntityManagerFactory for persistence unit 'ais'
  HHH000204: Processing PersistenceUnitInfo [
  
  
  HHH000130: Instantiating explicit connection provider: org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider
  HHH000400: Using dialect: **org.hibernate.dialect.MySQL5Dialect**
  HHH000268: Transaction strategy: org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory
  HHH000397: Using ASTQueryTranslatorFactory
  Loaded JDBC driver: com.mysql.jdbc.Driver
  </code></pre>
  
  <p>The next problem is the database access. Spring doesnt know which transaction manager it should use</p>
  
  <pre><code>: No qualifying bean of type [org.springframework.transaction.PlatformTransactionManager] is defined: expected single matching bean but found 2: aisjpatransactionManager,onlinejpaTransactionManager
  </code></pre>
  
  <p>Setting one tx manager as @Primary solves the issue above, but ends with table not found in the other lib, cause of the misconfigured tx manager / persistence unit.</p>
  
  <p>Perhaps my problem is the creating of LocalContainerEntityManagerFactoryBean for each individual jar. Instead i should use the following code to setup my db connection, but this would break my individual lib.</p>
  
  <pre><code>public LocalContainerEntityManagerFactoryBean internalEntityManagerFactory(
          EntityManagerFactoryBuilder builder) {
      Map&lt;String, Object&gt; properties = new HashMap&lt;String, Object&gt;();
      properties.put("hibernate.hbm2ddl.auto", "create");
      return builder
              .dataSource(internalDataSource())
              .packages("package here")
              .persistenceUnit("onlinjpa")
              .properties(properties)
              .build();
  }
  </code></pre>
  
  <p>How can i make each individual jar to work inside a Spring Boot application.</p>
  
  <p>Here's a link to set up multiple datasources with Sping Boot, but i dont want to configure my libs datasource inside the Spring Boot application. </p>
  
  <p><a href="https://stackoverflow.com/questions/28275448/multiple-data-source-and-schema-creation-in-spring-boot">Multiple data source and schema creation in Spring Boot</a></p>