I have a Spring MVC project with Hibernate (Spring 4.2.2 - Hibernate 4.3.6). I wanted to connect two datasources (two different postgresql databases) to it, so I used atomikos as implementation for JTA. I have my configuration all by annotations, so the Configuration file is this:
#Configuration
#PropertySource(value = { "classpath:hibernate.properties" })
public class HibernateConfig {
#Autowired
private Environment environment;
// First DB connection
#Primary
#Bean(name = "sessionFactory")
#DependsOn("setMyAtomikosSystemProps")
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "org.spring.model" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean(name = "statsSessionFactory")
#DependsOn("setMyAtomikosSystemProps")
public LocalSessionFactoryBean statsSessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(statsDataSource());
sessionFactory.setPackagesToScan(new String[] { "org.spring.stats.model" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Primary
#Bean(name = "dataSource")
public DataSource dataSource() {
AtomikosDataSourceBean ds = new AtomikosDataSourceBean();
ds.setUniqueResourceName("first");
ds.setXaDataSourceClassName("org.postgresql.xa.PGXADataSource");
ds.setXaProperties(dataSourceProperties("first"));
ds.setMinPoolSize(5);
ds.setMaxPoolSize(75);
ds.setMaxIdleTime(60 * 15);
return ds;
}
#Bean(name = "statsDataSource")
public DataSource statsDataSource() {
AtomikosDataSourceBean ds = new AtomikosDataSourceBean();
ds.setUniqueResourceName("second");
ds.setXaDataSourceClassName("org.postgresql.xa.PGXADataSource");
ds.setXaProperties(dataSourceProperties("second"));
ds.setMinPoolSize(5);
ds.setMaxPoolSize(75);
ds.setMaxIdleTime(60 * 15);
return ds;
}
private Properties dataSourceProperties(String database) {
Properties p = new Properties();
p.setProperty("user", environment.getRequiredProperty("hibernate.connection.username"));
p.setProperty("password", environment.getRequiredProperty("hibernate.connection.password"));
p.setProperty("serverName", environment.getRequiredProperty("hibernate.connection.url"))
p.setProperty("portNumber", environment.getRequiredProperty("hibernate.connection.port"))
p.setProperty("databaseName", database);
return p;
}
#Bean(name = "userTransactionService")
#DependsOn("setMyAtomikosSystemProps")
public UserTransactionService userTransactionService() {
UserTransactionServiceImp uts = new UserTransactionServiceImp();
Properties prop = new Properties();
prop.setProperty("com.atomikos.icatch.service", "com.atomikos.icatch.standalone.UserTransactionServiceFactory");
uts.init(prop);
return uts;
}
#Bean
#DependsOn("userTransactionService")
public UserTransactionManager AtomikosTransactionManager() {
UserTransactionManager utm = new UserTransactionManager();
utm.setForceShutdown(true);
utm.setStartupTransactionService(false);
return utm;
}
#Bean
#DependsOn("userTransactionService")
public UserTransaction AtomikosUserTransaction() {
UserTransactionImp ut = new UserTransactionImp();
try {
ut.setTransactionTimeout(300);
} catch (SystemException e) {
e.printStackTrace();
}
return ut;
}
#Bean
#DependsOn("userTransactionService")
public PlatformTransactionManager JtaTransactionManager() {
JtaTransactionManager jtaTM = new JtaTransactionManager();
jtaTM.setTransactionManager(AtomikosTransactionManager());
jtaTM.setUserTransaction(AtomikosUserTransaction());
jtaTM.setAllowCustomIsolationLevels(true);
return jtaTM;
}
// SharedProperties
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
// JTA
properties.put("hibernate.current_session_context_class", "jta");
properties.put("hibernate.transaction.factory_class", "org.hibernate.transaction.JTATransactionFactory");
properties.put("hibernate.transaction.jta.platform", "com.atomikos.icatch.jta.hibernate4.AtomikosPlatform");
return properties;
}
#Bean
public MethodInvokingFactoryBean setMyAtomikosSystemProps() {
MethodInvokingFactoryBean mifb = new MethodInvokingFactoryBean();
Properties p = new Properties();
p.setProperty("com.atomikos.icatch.hide_init_file_path", "true");
p.setProperty("com.atomikos.icatch.no_file", "true");
mifb.setArguments(new Object[] { p });
mifb.setTargetObject(java.lang.System.getProperties());
mifb.setTargetMethod("putAll");
return mifb;
}
}
This configuration works if the transaction involves only one datasource, but if I create a Service that wants get data from both, I receive this error:
GRAVE: Servlet.service() for servlet [dispatcher] in context with path [/api] threw exception [Request processing failed; nested exception is org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException: Prepare: NO vote] with root cause
com.atomikos.icatch.RollbackException: Prepare: NO vote
at com.atomikos.icatch.imp.ActiveStateHandler.prepare(ActiveStateHandler.java:202)
at com.atomikos.icatch.imp.CoordinatorImp.prepare(CoordinatorImp.java:523)
at com.atomikos.icatch.imp.CoordinatorImp.terminate(CoordinatorImp.java:687)
at com.atomikos.icatch.imp.CompositeTransactionImp.commit(CompositeTransactionImp.java:282)
at com.atomikos.icatch.jta.TransactionImp.commit(TransactionImp.java:172)
at com.atomikos.icatch.jta.TransactionManagerImp.commit(TransactionManagerImp.java:414)
at com.atomikos.icatch.jta.UserTransactionImp.commit(UserTransactionImp.java:86)
at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1021)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:485)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy91.findById(Unknown Source)
But this is NOT a timeout problem because the response come in few seconds.
I receive also a very long list of errors from postgres. I'm "filtering" the errors:
WARN XAResourceTransaction - XA resource 'second': rollback for XID '3139322E3136382E322E322E746D313438373639323737373736333030303032:3139322E3136382E322E322E746D32' raised -4: the supplied XID is invalid for this XA resource
org.postgresql.xa.PGXAException: Errore durante il «rollback» di una transazione preparata
(this one is in italian, it says "error during the "rollback" of a prepared transaction)
Caused by: org.postgresql.util.PSQLException: ERROR: prepared transactions are disabled
Suggerimento: Set max_prepared_transactions to a nonzero value.
Caused by: org.postgresql.util.PSQLException: ERROR: prepared transactions are disabled
Suggerimento: Set max_prepared_transactions to a nonzero value.
ERROR XAResourceTransaction - XA resource 'first': prepare for XID '3139322E3136382E322E322E746D313438373639323737373736333030303032:3139322E3136382E322E322E746D33' raised -3: the XA resource detected an internal error
org.postgresql.xa.PGXAException: Error in preparing transaction
So it seems it needs prepared transaction, but because only for transaction that include both of them? And it is mandatory enable them? Can I avoid this?
You have to edit your postgresql.conf file, find max_prepared_transactions and uncomment It (remove the # at the beginning of the line) and set a reasonable value.
See : https://www.postgresql.org/docs/9.4/static/runtime-config-resource.html
Related
I'm try to receive a weblogic server jms in spring boot . But I have encountered this problem after launch application successfully.
[]org.springframework.jms.listener.DefaultMessageListenerContainer:handleListenerSetupFailure(892): Setup of JMS message listener invoker failed for destination 'jms/test' - trying to recover. Cause: Access denied to resource: type=<jms>, application=JMSModule, destinationType=queue, resource=ns-alert-test, action=receive
And I found it can be connect successfully in thread of [main] when launching.
It looks like the username and password is missed when thread changed
[main] org.springframework.jndi.JndiObjectFactoryBean:lookup(112): Located object with JNDI name [jms/rtsConnectionFactory]
And I'm try to use wlfullclient.jar and wlclient.jar and wlthint3client.jar in my project . But the problem still exists. Can you give me some suggest of this problem . Below is my code
Config:
#Autowired
private JmsErrorHandler jmsErrorHandler;
#Autowired
private JMSPropertiesConfig jmsPropertiesConfig;
#Bean
public JndiTemplate jndiTemplate(){
JndiTemplate jndiTemplate =new JndiTemplate();
Properties properties = new Properties();
properties.setProperty("java.naming.factory.initial","weblogic.jndi.WLInitialContextFactory");
properties.setProperty("java.naming.provider.url", jmsPropertiesConfig.getUrl());
if(jmsPropertiesConfig.getUname()!=null){
properties.setProperty("username", jmsPropertiesConfig.getUname());
}
if(jmsPropertiesConfig.getUcert()!=null){
properties.setProperty("password", jmsPropertiesConfig.getUcert());
}
jndiTemplate.setEnvironment(properties);
return jndiTemplate;
}
#Bean
public JndiDestinationResolver jmsDestionationProvider() {
JndiDestinationResolver destinationResolver = new JndiDestinationResolver();
destinationResolver.setJndiTemplate(jndiTemplate());
return destinationResolver;
}
#Bean
public JndiObjectFactoryBean connectionFactory(){
JndiObjectFactoryBean cf = new JndiObjectFactoryBean();
cf.setJndiTemplate(jndiTemplate());
cf.setJndiName(jmsPropertiesConfig.getFactory());
return cf;
}
#Bean
public JmsTemplate jmsTemplate(){
JmsTemplate template = new JmsTemplate();
template.setConnectionFactory((ConnectionFactory) connectionFactory().getObject());
template.setSessionAcknowledgeModeName("AUTO_ACKNOWLEDGE");
template.setSessionTransacted(true);
template.setDestinationResolver(jmsDestionationProvider());
return template;
}
#Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory((ConnectionFactory) connectionFactory().getObject());
factory.setDestinationResolver(jmsDestionationProvider());
factory.setErrorHandler(jmsErrorHandler);
factory.setSessionAcknowledgeMode(0);
return factory;
}
Receive:
#JmsListener(destination = "jms/test")
public void receiveApplicationNotification(String input) throws Exception {
log.info("Receiving message from jms.external.ExampleQueue.queue "+input);
}
Seems to be a bug in Weblogic.
Can you please try applying below patch..
Bug 22550927 - WEBLOGIC JMS CONNECTION IS NOT THREAD-SAFE
I have configured a datasource configured on Oracle Weblogic 12.1.3 and trying to lookup this datasource in a Spring MVC application.
// Weblogic configuration
Datasource Name in weblogic : Admin Data Source
JNDI Name : bsh/AdminDS
// Spring MVC Configuration
#Bean
public DataSource getDataSourceUsingJndi() throws NamingException {
return (DataSource) new JndiTemplate().lookup("bsh/AdminDS"); // 1st way
}
#Bean
public LocalSessionFactoryBean sessionFactory() throws NamingException {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(getDataSourceUsingJndi());
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put(AvailableSettings.DIALECT, hibernateDialect);
properties.put(AvailableSettings.SHOW_SQL, showSql);
properties.put(AvailableSettings.FORMAT_SQL, formatSql);
return properties;
}
I am getting the below stacktrace:
Caused by: javax.naming.NameNotFoundException: Unable to resolve 'bsh.AdminDS'. Resolved 'bsh'; remaining name 'AdminDS'
at weblogic.jndi.internal.BasicNamingNode.newNameNotFoundException(BasicNamingNode.java:1180)
at weblogic.jndi.internal.BasicNamingNode.lookupHere(BasicNamingNode.java:270)
at weblogic.jndi.internal.ServerNamingNode.lookupHere(ServerNamingNode.java:187)
at weblogic.jndi.internal.BasicNamingNode.lookup(BasicNamingNode.java:210)
at weblogic.jndi.internal.BasicNamingNode.lookup(BasicNamingNode.java:224)
at weblogic.jndi.internal.WLEventContextImpl.lookup(WLEventContextImpl.java:253)
at weblogic.jndi.internal.WLContextImpl.lookup(WLContextImpl.java:426)
at javax.naming.InitialContext.lookup(InitialContext.java:417)
at org.springframework.jndi.JndiTemplate.lambda$lookup$0(JndiTemplate.java:156)
at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:91)
at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:156)
at com.bsh.config.WebConfig.getDataSourceUsingJndi(WebConfig.java:68)
I tried different ways to lookup - 2nd way
public DataSource getDataSourceUsingJndi() {
JndiDataSourceLookup jndiLookup = new JndiDataSourceLookup();
jndiLookup.setResourceRef(true);
return jndiLookup.getDataSource("bsh/AdminDS");
}
Is there anything wrong with my configuration ?
I am working on application written in spring Boot 1.5.3. I have two data source which are configured as below.
Main connection
spring.datasource.driverClassName = org.postgresql.Driver
spring.datasource.url = jdbc:postgresql://xxx.xxx.xxx.xx:5432/mydb
spring.datasource.username = xxxx
spring.datasource.password = xxxx
spring.jpa.properties.hibernate.default_schema=test
# Number of ms to wait before throwing an exception if no connection is available.
spring.datasource.tomcat.max-wait=10000
# Maximum number of active connections that can be allocated from this pool at the same time.
spring.datasource.tomcat.max-active=150
spring.datasource.tomcat.max-idle=30
spring.datasource.tomcat.min-idle=2
spring.datasource.tomcat.initial-size=3
# Validate the connection before borrowing it from the pool.
spring.datasource.tomcat.test-on-borrow=true
spring.datasource.tomcat.test-on-connect=true
spring.datasource.time-between-eviction-runs-millis=60000
#spring.datasource.tomcat.validation-query-timeout=1000
spring.datasource.tomcat.validation-query=SELECT 1
spring.datasource.tomcat.validation-interval=1000
spring.datasource.tomcat.remove-abandoned=true
spring.datasource.tomcat.remove-abandoned-timeout=55
spring.datasource.tomcat.test-while-idle=true
spring.datasource.tomcat.min-evictable-idle-time-millis = 55000
spring.datasource.tomcat.time-between-eviction-runs-millis = 34000
Second Connection
spring.rdatasource.driverClassName = org.postgresql.Driver
spring.rdatasource.url = jdbc:postgresql://xxx.xxx.xxx.xx:5432/mydb1
spring.rdatasource.username = xxxx
spring.rdatasource.password = xxxx
spring.jpa.properties.hibernate.default_schema=test
# Number of ms to wait before throwing an exception if no connection is available.
spring.rdatasource.tomcat.max-wait=10000
# Maximum number of active connections that can be allocated from this pool at the same time.
spring.rdatasource.tomcat.max-active=150
spring.rdatasource.tomcat.max-idle=30
spring.rdatasource.tomcat.min-idle=2
spring.rdatasource.tomcat.initial-size=3
# Validate the connection before borrowing it from the pool.
spring.rdatasource.tomcat.test-on-borrow=true
spring.rdatasource.tomcat.test-on-connect=true
spring.rdatasource.time-between-eviction-runs-millis=60000
#spring.rdatasource.tomcat.validation-query-timeout=1000
spring.rdatasource.tomcat.validation-query=SELECT 1
spring.rdatasource.tomcat.validation-interval=1000
spring.rdatasource.tomcat.remove-abandoned=true
spring.rdatasource.tomcat.remove-abandoned-timeout=55
spring.rdatasource.tomcat.test-while-idle=true
spring.rdatasource.tomcat.min-evictable-idle-time-millis = 55000
spring.rdatasource.tomcat.time-between-eviction-runs-millis = 34000
I am working in in VPN environment. When I run application, application is working fine. But the issue starts when I disconnect the VPN and reconnect the VPN.again, my application won't reconnect to data source again. Instead I always getting exception.
But working single database when leave connection handling to spring itself and I do not perform any database configuration.
Update
#Configuration
#PropertySource({ "classpath:application.properties" })
#EnableJpaRepositories(
basePackages = {"com.services.persistence"},
entityManagerFactoryRef = "entityManager",
transactionManagerRef = "transactionManager"
)
#ComponentScan("com.services.persistence")
#EnableTransactionManagement
public class DBConfig {
#Autowired private Environment env;
#Bean
#Primary
public LocalContainerEntityManagerFactoryBean entityManager() {
LocalContainerEntityManagerFactoryBean em
= new LocalContainerEntityManagerFactoryBean();
em.setDataSource(userDataSource());
em.setPackagesToScan(
new String[] { "com.services.persistence", "com.services.persistence.pojo" });
HibernateJpaVendorAdapter vendorAdapter
= new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
HashMap<String, Object> properties = new HashMap<>();
// properties.put("hibernate.hbm2ddl.auto",
// env.getProperty("hibernate.hbm2ddl.auto"));
properties.put("hibernate.dialect",
env.getProperty("spring.jpa.database-platform"));
properties.put("hibernate.current_session_context_class",
env.getProperty("spring.jpa.properties.hibernate.current_session_context_class"));
em.setJpaPropertyMap(properties);
return em;
}
#Primary
#Bean
#ConfigurationProperties(prefix = "spring.datasource")
public DataSource userDataSource() {
return DataSourceBuilder
.create()
.build();
}
#Primary
#Bean
public JpaTransactionManager transactionManager() {
JpaTransactionManager transactionManager
= new JpaTransactionManager();
transactionManager.setEntityManagerFactory(
entityManager().getObject());
return transactionManager;
}
#Bean(name = "sessionFactory")
public SessionFactory getSessionFactory() {
SessionFactory sessionFactory = transactionManager().getEntityManagerFactory().unwrap(SessionFactory.class);
if (sessionFactory == null) {
throw new NullPointerException("factory is not a hibernate factory");
} else {
System.out.println(
"==================================== Transaction Enabled ========================================");
return sessionFactory;
}
}
I have also configured spring.rdatasource and it is same as above file, except it is not set as primary and other further details like pojo, transactionmanager etc.
I am new to spring batch and I have a spring batch with spring data project with oracle database. Basically for simplicity I have 2 steps :
Step 1 : Read the first row of the csv file than insert in table_header in itemwriter
Step 2 : Read from the second row of the csv file than insert in table_detail in itemwriter.
The table_header is linked to table_detail - one to many relationship.
Basically if a runtime exception in triggered in step 2 just after saving the detail while in the same step the data does not roll back.According to spring reference it should roll back on runtime exception.
I am not sure what i am missing in order for the transaction to rollback, can someone point me to the right direction pls?
Please find below my database configuration:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(entityManagerFactoryRef = "dummyEntityManager", transactionManagerRef = "dummyTransactionManager", basePackages = {
"com.dummy.persistence" })
#PropertySource("file:${test_PROPERTIES}")
public class DatabaseConfig extends HikariConfig {
#Bean(name = "dummyDatasource")
public HikariDataSource dataSource() {
HikariDataSource hikariDataSource = new HikariDataSource();
hikariDataSource.setJdbcUrl(CipherWrapper.getInstance().decrypt(jdbcUrl));
hikariDataSource.setUsername(CipherWrapper.getInstance().decrypt(username));
hikariDataSource.setPassword(CipherWrapper.getInstance().decrypt(password));
hikariDataSource.setAutoCommit(false);
hikariDataSource.setMaximumPoolSize(maximumPoolSize);
hikariDataSource.setMinimumIdle(minimumIdle);
return hikariDataSource;
}
#Bean(name = "dummyEntityManager")
public LocalContainerEntityManagerFactoryBean dummyEntityManagerFactory(EntityManagerFactoryBuilder builder) {
LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = builder.dataSource(dataSource())
.packages("com.dummy.persistence.entity").persistenceUnit("dummyPersistenceUnit").build();
localContainerEntityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
return localContainerEntityManagerFactoryBean;
}
#Bean(name = "dummyTransactionManager")
public PlatformTransactionManager dummyTransactionManager(
#Qualifier("dummyEntityManager") EntityManagerFactory dummyEntityManagerFactory) {
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager(dummyEntityManagerFactory);
jpaTransactionManager.setRollbackOnCommitFailure(true);
return jpaTransactionManager;
}
#Bean
public BatchConfigurer batchConfigurer(#Qualifier("dummyEntityManager") EntityManagerFactory dummyEntityManagerFactory) {
return new DefaultBatchConfigurer() {
#Override
public PlatformTransactionManager getTransactionManager() {
return dummyTransactionManager(dummyTransactionManager);
}
};
}
}
Please find below both step config:
#Bean("step1")
public Step headerSaveStep() {
StepBuilder stepBuilder = stepBuilderFactory.get(Flow.STEP1.toString());
SimpleStepBuilder<HeaderDetailsDto,HeaderDetailsAdditionaDto> simpleStepBuilder = stepBuilder
.<HeaderDetailsDto, HeaderDetailsAdditionaDto>chunk(1);
simpleStepBuilder.reader(csvItemReader.csvFileVatPayerDetailsItemReader(null));
simpleStepBuilder.processor(EnrichmentProcessor());
simpleStepBuilder.writer(headerWriter());
simpleStepBuilder.allowStartIfComplete(true);
return simpleStepBuilder.build();
}
#Bean("step2")
public Step detailSaveStep() {
StepBuilder stepBuilder = stepBuilderFactory.get(Flow.STEP2.toString());
SimpleStepBuilder<DetailsDto, DetailsDto> simpleStepBuilder = stepBuilder
.<DetailsDto, DetailsDto>chunk(20000);
simpleStepBuilder.reader(csvItemReader.csvFileBuyerDetailsFileItemReader(null));
simpleStepBuilder.writer(detailsWriter());
simpleStepBuilder.allowStartIfComplete(true);
return simpleStepBuilder.build();
}
Your transaction manager is not being used by Spring Batch. You need to define a BatchConfigurer bean referring to it (See example here). Hope this helps.
I need to create a Camel route that polls a DB, transforms the retrieved data and then inserts the new entities into another DB. I need help with the configuration.
These are the jpa endpoints:
from("jpa://" + Entity1.class.getName()
+ "?"
+ "persistenceUnit=entity1PU&"
+ "consumer.namedQuery=query1&"
+ "consumeDelete=false"
)
//various operations...
.to("direct:route2");
from("direct:route2")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
//processing...
}
})
.to("jpa://" + Entity2.class.getName()
+ "?"
+ "persistenceUnit=entity2PU&"
+ "entityType=java.util.ArrayList&"
+ "usePersist=true&"
+ "flushOnSend=true");
I'd like to configure the persistence units by code and annotations, instead of using persistence.xml; these are the relative classes. This is the first:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
basePackages = "com.foo.entity1.repo",
entityManagerFactoryRef = "entity1EntityManagerFactory",
transactionManagerRef = "entity1TransactionManager"
)
public class Entity1PersistenceConfig {
#Autowired
#Qualifier("datasource1")
private DataSource dataSource;
#Primary
public DataSource dataSource() {
return this.dataSource;
}
#Primary
#Bean(name="entity1EntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.foo.entity1.domain");
factory.setDataSource(this.dataSource());
factory.setPersistenceProviderClass(HibernatePersistenceProvider.class);
factory.setPersistenceUnitName("entity1PU");
Properties hibernateProps = setJpaHibernateCommonProperties();
hibernateProps.setProperty("hibernate.dialect", environment.getProperty("spring.jpa.properties.hibernate.oracle.dialect"));
factory.setJpaProperties(hibernateProps);
return factory;
}
#Primary
#Bean(name="entity1TransactionManager")
public PlatformTransactionManager transactionManager() {
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return jpaTransactionManager;
}
}
and the second one:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
basePackages = "com.foo.entity2.repo",
entityManagerFactoryRef = "entity2EntityManagerFactory",
transactionManagerRef = "entity2TransactionManager"
)
public class Entity2PersistenceConfig {
#Autowired
#Qualifier("datasource2")
private DataSource dataSource;
public DataSource dataSource() {
return this.dataSource;
}
#Bean(name="entity2EntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.foo.entity2.domain");
factory.setDataSource(this.dataSource());
factory.setPersistenceProviderClass(HibernatePersistenceProvider.class);
factory.setPersistenceUnitName("entity2PU");
Properties hibernateProps = setJpaHibernateCommonProperties();
hibernateProps.setProperty("hibernate.dialect", environment.getProperty("spring.jpa.properties.hibernate.mysql.dialect"));
factory.setJpaProperties(hibernateProps);
return factory;
}
#Bean(name="entity2TransactionManager")
public PlatformTransactionManager transactionManager() {
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return jpaTransactionManager;
}
}
Entities and repositories are in the correct packages; also, the configuration of the databases is correctly done in a specific class, and are correctly injected.
When I try to run the project, I get the following:
2018-05-30 11:38:36.481 INFO 1056 --- [main] o.h.j.b.internal.PersistenceXmlParser: HHH000318: Could not find any META-INF/persistence.xml file in the classpath
and
javax.persistence.PersistenceException: No Persistence provider for EntityManager named entity1PU
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:61) ~[hibernate-jpa-2.1-api-1.0.0.Final.jar:1.0.0.Final]
at org.springframework.orm.jpa.LocalEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalEntityManagerFactoryBean.java:96) ~[spring-orm-4.3.17.RELEASE.jar:4.3.17.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) ~[spring-orm-4.3.17.RELEASE.jar:4.3.17.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) ~[spring-orm-4.3.17.RELEASE.jar:4.3.17.RELEASE]
at org.apache.camel.component.jpa.JpaEndpoint.createEntityManagerFactory(JpaEndpoint.java:552) ~[camel-jpa-2.21.1.jar:2.21.1]
at org.apache.camel.component.jpa.JpaEndpoint.getEntityManagerFactory(JpaEndpoint.java:250) ~[camel-jpa-2.21.1.jar:2.21.1]
at org.apache.camel.component.jpa.JpaEndpoint.validate(JpaEndpoint.java:545) ~[camel-jpa-2.21.1.jar:2.21.1]
at org.apache.camel.component.jpa.JpaEndpoint.createConsumer(JpaEndpoint.java:165) ~[camel-jpa-2.21.1.jar:2.21.1]
at org.apache.camel.impl.EventDrivenConsumerRoute.addServices(EventDrivenConsumerRoute.java:69) ~[camel-core-2.21.1.jar:2.21.1]
at org.apache.camel.impl.DefaultRoute.onStartingServices(DefaultRoute.java:103) ~[camel-core-2.21.1.jar:2.21.1]
at org.apache.camel.impl.RouteService.doWarmUp(RouteService.java:172) ~[camel-core-2.21.1.jar:2.21.1]
at org.apache.camel.impl.RouteService.warmUp(RouteService.java:145) ~[camel-core-2.21.1.jar:2.21.1]
Why is it looking for a persistence.xml file instead of using annotations? I'm using Spring Boot 1.5.13.RELEASE with Camel 2.21.1.
Basically to make it work I had to abandon using annotations and create an equivalent persistence.xml file, because Apache Camel was looking for configuration only in it.
As soon as I could upgrade to Spring Boot 2 (because Apache Camel got updated and started to support it), I managed to make configuration by annotations work and dropped the persistence.xml file.