i have a simple Spring Boot application with 2 external jars. Each jar uses Spring JPA and is completely configured to work standalone.
Jar1
JPA Repository
@Repository
public interface QuarterRepository extends JpaRepository<Quarter, Long>{
}
Entity
@Entity
public class Quarter implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;...
Configurations
@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;
}
}
The second jar looks almost the same as Jar1, except the bean and the package names
@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;
}
}
Running this Main class in Jar1 gives the expected results.. ( The same as for Jar2)
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(OnlineJpaAppConfig.class);
QuarterRepository quarterRepository = ctx.getBean("quarterRepository", QuarterRepository.class);
List<Quarter> quarters = quarterRepository.findAll();
for (Quarter quarter : quarters) {
System.out.println(quarter.getQuarter());
}
}
}
This is the startup class of my Spring Boot application
@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);
}
}
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 Jar1.
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
The next problem is the database access. Spring doesnt know which transaction manager it should use
: No qualifying bean of type [org.springframework.transaction.PlatformTransactionManager] is defined: expected single matching bean but found 2: aisjpatransactionManager,onlinejpaTransactionManager
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.
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.
public LocalContainerEntityManagerFactoryBean internalEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("hibernate.hbm2ddl.auto", "create");
return builder
.dataSource(internalDataSource())
.packages("package here")
.persistenceUnit("onlinjpa")
.properties(properties)
.build();
}
How can i make each individual jar to work inside a Spring Boot application.
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.