Transaction in jboss eap JmsComponent camel context - jboss

I'm having troubles setting up transactions using JtaTransactionManager. I've tried everything I could find in internet.
I want to make rollback if there is any Exception in the route or in the routes coming from this route.
Here is my camel context beans:
<bean id="jmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:/JmsMQXA" />
<property name="lookupOnStartup" value="false" />
<property name="cache" value="true" />
<property name="proxyInterface" value="javax.jms.ConnectionFactory" />
</bean>
<bean id="jmsTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName" value="java:/TransactionManager" />
</bean>
<bean id="mq" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="jmsConnectionFactory" />
<property name="transacted" value="true"/>
<property name="cacheLevelName" value="CACHE_NONE" />
<property name="transactionManager" ref="jmsTransactionManager" />
</bean>
<bean id="PROPAGATION_REQUIRED" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
<property name="transactionManager" ref="jmsTransactionManager" />
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRES_NEW" />
</bean>
My route:
<route>
<from uri="mq:TEST.QUEUE" />
<transacted ref="PROPAGATION_REQUIRED"/>
MY standalone
<subsystem xmlns="urn:jboss:domain:resource-adapters:5.0">
<resource-adapters>
<resource-adapter id="wmq.jmsra.rar">
<archive>
wmq.jmsra.rar
</archive>
<transaction-support>XATransaction</transaction-support>...
And the problems I get:
WARN [org.apache.camel.spring.spi.TransactionErrorHandler] (Camel (camel-1) thread #1 - JmsConsumer[TEST.QUEUE]) Transaction rollback (0x68e69794) redelivered(true) for (MessageId: ID:414d51205141424749434c4441202020ab7e795dfb630223 on ExchangeId: ID-M0AB1I4O-1572259802058-0-7) caught
INFO [org.jboss.as.connector.deployers.RaXmlDeployer] (Camel (camel-1) thread #1 - JmsConsumer[TEST.QUEUE]) wmq.jmsra.rar: MQJCA4026:Transaction backed out with reason: 'The method 'xa_end' has failed with errorCode '100'.'.
WARN [com.arjuna.ats.jta] (Camel (camel-1) thread #1 - JmsConsumer[TEST.QUEUE]) ARJUNA016045: attempted rollback of < formatId=131077, gtrid_length=29, bqual_length=36, tx_uid=0:ffff0ae317d6:-21705625:5db6b586:1f48, node_name=1, branch_uid=0:ffff0ae317d6:-21705625:5db6b586:1f4c, subordinatenodename=null, eis_name=java:/JmsMQXA > (XAResourceWrapperImpl#258df727[xaResource=com.ibm.mq.connector.xa.XARWrapper#4e359608 pad=false overrideRmValue=null productName=WebSphere MQ productVersion=%I% %E% %U% jndiName=java:/JmsMQXA]) failed with exception code XAException.XAER_NOTA: javax.transaction.xa.XAException: The method 'xa_rollback' has failed with errorCode '-4'.
at com.ibm.mq.jmqi.JmqiXAResource.rollback(JmqiXAResource.java:874)
at com.ibm.mq.connector.xa.XARWrapper.rollback(XARWrapper.java:598)
at org.jboss.jca.core.tx.jbossts.XAResourceWrapperImpl.rollback(XAResourceWrapperImpl.java:196)
at com.arjuna.ats.internal.jta.resources.arjunacore.XAResourceRecord.topLevelAbort(XAResourceRecord.java:362)
at com.arjuna.ats.arjuna.coordinator.BasicAction.doAbort(BasicAction.java:3023)
at com.arjuna.ats.arjuna.coordinator.BasicAction.doAbort(BasicAction.java:3002)
at com.arjuna.ats.arjuna.coordinator.BasicAction.Abort(BasicAction.java:1674)
at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.cancel(TwoPhaseCoordinator.java:124)
at com.arjuna.ats.arjuna.AtomicAction.abort(AtomicAction.java:186)
at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.rollbackAndDisassociate(TransactionImple.java:1371)
at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.rollback(BaseTransaction.java:143)
at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.rollback(BaseTransactionManagerDelegate.java:134)
at org.wildfly.transaction.client.LocalTransaction.rollbackAndDissociate(LocalTransaction.java:104)
at org.wildfly.transaction.client.ContextTransactionManager.rollback(ContextTransactionManager.java:83)
at org.wildfly.transaction.client.LocalUserTransaction.rollback(LocalUserTransaction.java:58)
at org.springframework.transaction.jta.JtaTransactionManager.doRollback(JtaTransactionManager.java:1048)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:857)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:717)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:249)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1168)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1160)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1057)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

There was an older issue with WebSphere MQ, I can now only find quickly this reference https://developer.jboss.org/thread/250976
Maybe it gives you a hint (and in any case, trace logs on the MQ server could show more info)

There are a couple of problems with your code snippet. The JmsTransactionManager should not be assigned from the NDI transaction manager - which is a JTA transaction manager. Note that if you set you component as 'transacted' and provide a connection factory, then Spring JMS will instantiate a JmsTransactionManager for you and wire it up to the connection factory. So, just:
<bean id="mq" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="jmsConnectionFactory" />
<property name="transacted" value="true"/>
<property name="cacheLevelName" value="CACHE_NONE" />
<property name="receiveTimeout" value="100000"/>
And then drop:
<bean id="jmsTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName" value="java:/TransactionManager" />
and:
<bean id="PROPAGATION_REQUIRED"
class="org.apache.camel.spring.spi.SpringTransactionPolicy">
<property name="transactionManager" ref="jmsTransactionManager" />
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRES_NEW" />
Maybe try something like:
<bean class="com.ibm.mq.jms.MQConnectionFactory" id="source.mqConnectionFactory">
<property name="connectionNameList" value="10.0.0.207(1414)"/>
<property name="queueManager" value="MY.QUEUE.MANAGER"/>
<property name="channel" value="SYSTEM.DEF.SVRCONN"/>
<property name="transportType" value="1"/>
<property name="clientReconnectOptions" value="67108864"/>
</bean>
<bean
class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter" id="source.mqUserCred">
<property name="targetConnectionFactory" ref="source.mqConnectionFactory"/>
<property name="username" value="my-password"/>
</bean>
<bean class="org.apache.activemq.jms.pool.PooledConnectionFactory"
id="source.pooledConnectionFactory" primary="true">
<property name="maxConnections" value="1"/>
<property name="idleTimeout" value="0"/>
<property name="connectionFactory" ref="source.mqUserCred"/>
</bean>
<bean class="org.apache.camel.component.jms.JmsComponent" id="source">
<property name="configuration">
<bean class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="source.pooledConnectionFactory"/>
<property name="transacted" value="true"/>
<property name="receiveTimeout" value="100000"/>
<property name="maxConcurrentConsumers" value="5"/>
</bean>
</property>
</bean>

Related

Spring batch: how to configure xa transactions

This is my situation:
a Postgres database where I have only Spring Batch tables
an Oracle database where I have business data to read, write and update
I have tried to configure an XA enviroment with Atomikos and it seems to work but honestly I haven't understand what is exactly happening.
Can you check my configuration, please? I'm totally noob in these things...
If I set "hibernate.transaction.jta.platform" to "com.atomikos.icatch.jta.hibernate4.AtomikosPlatform" instead of my class "SpringJtaPlatformAdapter" it seems that the batch doesn't commit on my Postgres DB. Why?
For testing I was using Spring "JpaPagingItemReader". With this reader I get always the exception "java.lang.IllegalStateException: A JTA EntityManager cannot use getTransaction()" so I copied this solution: solution
Why I need to do this? Is there another JpaReader for XA?
Thanks a lot for your help.
Here my configuration:
spring-batch-core 3.0.7.RELEASE
spring-jdbc and spring-orm 4.0.5.RELEASE
hibernate-entitymanager 5.0.7.Final
Atomikos transactions-jta, transactions-jdbc, transactions-hibernate4 4.0.6
database.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="oracleDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
init-method="init" destroy-method="close">
<property name="xaDataSourceClassName" value="oracle.jdbc.xa.client.OracleXADataSource" />
<property name="uniqueResourceName" value="oracleDS" />
<property name="minPoolSize" value="1" />
<property name="maxPoolSize" value="3"/>
<property name="testQuery" value="select * from dual" />
<property name="xaProperties">
<props>
<prop key="URL">${database.oracle.url}</prop>
<prop key="user">${database.oracle.username}</prop>
<prop key="password">${database.oracle.password}</prop>
</props>
</property>
</bean>
<bean id="postgresDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
init-method="init" destroy-method="close">
<property name="xaDataSourceClassName" value="org.postgresql.xa.PGXADataSource" />
<property name="uniqueResourceName" value="postgresDS" />
<property name="minPoolSize" value="1" />
<property name="maxPoolSize" value="3"/>
<property name="testQuery" value="select * from batch_job_execution" />
<property name="xaProperties">
<props>
<prop key="serverName">localhost</prop>
<prop key="databaseName">postgres</prop>
<prop key="user">${database.postgresql.username}</prop>
<prop key="password">${database.postgresql.password}</prop>
</props>
</property>
</bean>
<bean id="atomikosTransactionService" class="com.atomikos.icatch.config.UserTransactionServiceImp"
init-method="init" destroy-method="shutdownForce">
<constructor-arg>
<props>
<prop key="com.atomikos.icatch.service">com.atomikos.icatch.standalone.UserTransactionServiceFactory</prop>
<prop key="com.atomikos.icatch.tm_unique_name">coriTransactionManager</prop>
</props>
</constructor-arg>
</bean>
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp" depends-on="atomikosTransactionService">
<property name="transactionTimeout" value="300" />
</bean>
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" depends-on="atomikosTransactionService" destroy-method="close">
<property name="forceShutdown" value="true" />
<property name="startupTransactionService" value="false" />
</bean>
<bean id="mainTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="atomikosTransactionManager" />
<property name="userTransaction" ref="atomikosUserTransaction" />
</bean>
<alias name="mainTransactionManager" alias="transactionManager" />
<!-- inject the Atomikos transaction manager into a Spring Hibernate adapter for JTA Platform -->
<bean id="springJtaPlatformAdapter" class="com.mydomain.jta.SpringJtaPlatformAdapter">
<property name="jtaTransactionManager" ref="mainTransactionManager" />
</bean>
<bean id="entityManagerFactoryOracle" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
depends-on="mainTransactionManager,springJtaPlatformAdapter">
<property name="persistenceXmlLocation" value="classpath:persistence.xml" />
<property name="persistenceUnitName" value="oraclePersistenceUnit" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapterOracle"/>
<property name="dataSource" ref="oracleDataSource" />
<property name="jpaPropertyMap" ref="jpaPropertyMapOracle"></property>
</bean>
<bean id="jpaVendorAdapterOracle" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="false"/>
<property name="showSql" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
</bean>
<util:map id="jpaPropertyMapOracle">
<entry key="hibernate.transaction.jta.platform" value="com.mydomain.jta.SpringJtaPlatformAdapter" />
<!-- <entry key="hibernate.transaction.jta.platform" value="com.atomikos.icatch.jta.hibernate4.AtomikosPlatform"/> -->
</util:map>
</beans>
context.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<property name="dataSource" ref="postgresDataSource" />
<property name="transactionManager" ref="transactionManager" />
<property name="databaseType" value="POSTGRES" />
<property name="isolationLevelForCreate" value="ISOLATION_DEFAULT"/>
</bean>
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
</beans>
SpringJtaPlatformAdapter
public class SpringJtaPlatformAdapter extends AbstractJtaPlatform {
private static final long serialVersionUID = 1L;
private static TransactionManager sTransactionManager;
private static UserTransaction sUserTransaction;
#Override
protected TransactionManager locateTransactionManager() {
return sTransactionManager;
}
#Override
protected UserTransaction locateUserTransaction() {
return sUserTransaction;
}
public void setJtaTransactionManager(JtaTransactionManager jtaTransactionManager) {
sTransactionManager = jtaTransactionManager.getTransactionManager();
sUserTransaction = jtaTransactionManager.getUserTransaction();
}
}

NonTransientFlatFileException in Spring Batch

I was trying to read a CSV file having 100 records and processing them in a batch of 10 records in one go. Everything is working fine but after processing all the records, i am getting
org.springframework.batch.item.file.NonTransientFlatFileException:
Unable to read from resource: [class path resource
[csv/input/VMwareImport.csv]] and the root cause is
org.springframework.batch.core.JobExecutionException: Partition
handler returned an unsuccessful step.
Below is my job xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:batch="http://www.springframework.org/schema/batch" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/batch
http://www.springframework.org/schema/batch/spring-batch-2.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<import resource="../config/context.xml" />
<bean id="report" class="com.abc.model.VMware" scope="prototype" />
<bean id="itemProcessor" class="com.abc.CustomItemProcessor" scope="step">
<property name="threadName" value="#{stepExecutionContext[name]}" />
</bean>
<batch:job id="vmImport">
<batch:step id="step1">
<partition step="slave" partitioner="rangePartitioner">
<handler grid-size="10" task-executor="taskExecutor" />
</partition>
</batch:step>
</batch:job>
<batch:step id="slave">
<batch:tasklet>
<batch:chunk reader="cvsFileItemReader" writer="xmlItemWriter"
processor="itemProcessor" commit-interval="10" />
</batch:tasklet>
</batch:step>
<bean id="rangePartitioner" class="com.abc.partition.RangePartitioner" />
<bean id="taskExecutor" class="org.springframework.core.task.SimpleAsyncTaskExecutor" />
<bean id="cvsFileItemReader" class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="resource" value="classpath:csv/input/VMwareImport.csv" />
<property name="lineMapper">
<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="lineTokenizer">
<bean
class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="names" value="SubscriptionId,TemplateName,ResourcePool,CpuCount,MemorySize,Network,DiskSize,
StorageCluster,DHCP,StaticIP,Subnet,Gateway,DNS1,DNS2,
DtapTag,FinTag,TechTag,TshirtTag,BackupTag " />
</bean>
</property>
<property name="fieldSetMapper">
<bean class="com.abc.VMwareFieldSetMapper" />
<!-- if no data type conversion, use BeanWrapperFieldSetMapper to map
by name <bean class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
<property name="prototypeBeanName" value="report" /> </bean> -->
</property>
</bean>
</property>
</bean>
<!-- <bean id="cvsFileItemReader" class="com.abc.VMwareReaderFromFile" scope="step">
<constructor-arg value="classpath:csv/input/VMwareImport.csv" />
</bean> -->
<bean id="xmlItemWriter" class="com.abc.DummyWriter">
<!-- <property name="resource" value="file:xml/outputs/report.xml" /> <property
name="marshaller" ref="reportMarshaller" /> <property name="rootTagName"
value="report" /> -->
</bean>
<!-- <bean id="reportMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound"> <list> <value>com.abc.model.VMware</value>
</list> </property> </bean> -->
Complete Exception StackTrace:
org.springframework.batch.item.file.NonTransientFlatFileException: Unable to read from resource: [class path resource [csv/input/VMwareImport.csv]]
at org.springframework.batch.item.file.FlatFileItemReader.readLine(FlatFileItemReader.java:220)
at org.springframework.batch.item.file.FlatFileItemReader.doRead(FlatFileItemReader.java:173)
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.read(AbstractItemCountingItemStreamItemReader.java:83)
at org.springframework.batch.core.step.item.SimpleChunkProvider.doRead(SimpleChunkProvider.java:91)
at org.springframework.batch.core.step.item.SimpleChunkProvider.read(SimpleChunkProvider.java:155)
at org.springframework.batch.core.step.item.SimpleChunkProvider$1.doInIteration(SimpleChunkProvider.java:114)
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:368)
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144)
at org.springframework.batch.core.step.item.SimpleChunkProvider.provide(SimpleChunkProvider.java:108)
at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:69)
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:395)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:131)
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:267)
at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:77)
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:368)
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144)
at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:253)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:195)
at org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler$1.call(TaskExecutorPartitionHandler.java:139)
at org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler$1.call(TaskExecutorPartitionHandler.java:136)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.lang.Thread.run(Thread.java:744)
Caused by: java.io.IOException: Stream closed
at java.io.BufferedReader.ensureOpen(BufferedReader.java:115)
at java.io.BufferedReader.readLine(BufferedReader.java:310)
at java.io.BufferedReader.readLine(BufferedReader.java:382)
at org.springframework.batch.item.file.FlatFileItemReader.readLine(FlatFileItemReader.java:201)
... 23 more
SEVERE: Encountered an error executing the step
org.springframework.batch.core.JobExecutionException: Partition handler returned an unsuccessful step
at org.springframework.batch.core.partition.support.PartitionStep.doExecute(PartitionStep.java:111)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:195)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:137)
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:64)
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:152)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:131)
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:301)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:134)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:49)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:127)
at com.fujitsu.App.main(App.java:27)
Your cvsFileItemReader needs to be step scoped. Whichever partition finishes first is closing the stream so the other partitions are unable to continue reading.

groovy + spring integration jpa: linkage error

Using Spring integration JPA + Groovy
I got the following error:
Could not instantiate bean class [org.springframework.integration.jpa.core.JpaExecutor]: Constructor threw exception; nested exception is java.lang.LinkageError: loader constraint violation: loader (instance of groovy/lang/GroovyClassLoader) previously initiated loading for a different type with name "javax/persistence/LockModeType"
Here are my dependencies :
dependencies {
compile 'org.springframework.integration:spring-integration-jpa:3.0.4.RELEASE'
compile 'org.apache.openjpa:openjpa:2.3.0'
compile group: 'hsqldb', name: 'hsqldb', version: '1.8.0.10'
compile 'org.codehaus.groovy:groovy-all:2.3.6'
}
Here is my spring context :
<int-jpa:inbound-channel-adapter
channel="jpaInboundChannel"
entity-manager="entityManagerFactory"
jpa-query="select p from Person p"
auto-startup="true" >
<int:poller fixed-rate="2000">
</int:poller>
</int-jpa:inbound-channel-adapter>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<constructor-arg ref="entityManagerFactory" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="vendorAdaptor" />
<property name="packagesToScan" value="com.univ"/>
</bean>
<jdbc:embedded-database id="dataSource" type="HSQL" />
<bean id="vendorAdaptor" class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter"
parent="abstractVendorAdaptor">
</bean>
<bean id="abstractVendorAdaptor" abstract="true">
<property name="generateDdl" value="true" />
<property name="database" value="HSQL" />
<property name="showSql" value="false"/>
</bean>
<int:service-activator input-channel="jpaInboundChannel" ref="service" method="method"></int:service-activator>
<bean id="service" class="com.univ.Service" />
The Groovy main programs contains :
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:META-INF/applicationContext.xml")
What can I do ? Thank you.

How to disable quartz load balancing?

I have this scheduler :
<bean id="odilQuartzScheduler"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean"
lazy-init="false">
<property name="jobFactory">
<bean class="org.springframework.scheduling.quartz.SpringBeanJobFactory"/>
</property>
<property name="schedulerName" value="OdilScheduler"/>
<property name="applicationContextSchedulerContextKey" value="applicationContext"/>
<property name="autoStartup" value="${popo.scheduler}"/>
<property name="startupDelay" value="60"/>
<property name="overwriteExistingJobs" value="true"/>
<property name="configLocation" value="classpath:quartz-odil.properties"/>
<property name="transactionManager" ref="applicationTransactionManager"/>
<property name="schedulerContextAsMap">
<map>
<entry key="globalConfiguration" value-ref="globalConfiguration"/>
<entry key="odilFileImporter" value-ref="odilFileImporter"/>
<entry key="odilRemoteDispatcher" value-ref="odilRemoteDispatcher"/>
<entry key="odilService" value-ref="odilService"/>
<entry key="centreReferenceService" value-ref="centreReferenceService"/>
<entry key="envoiParserFactory" value-ref="envoiParserFactory"/>
<entry key="versionReferenceService" value-ref="versionReferenceService"/>
<entry key="delPublisherService" value-ref="delPublisherService"/>
<entry key="capteurPublisherService" value-ref="capteurPublisherService"/>
</map>
</property>
<property name="triggers">
<list>
<ref bean="piloteOdilTrigger-1"/>
<ref bean="piloteOdilTrigger-2"/>
<ref bean="piloteOdilTrigger-3"/>
<ref bean="piloteOdilTrigger-4"/>
<ref bean="piloteOdilTrigger-5"/>
<ref bean="piloteOdilTrigger-6"/>
</list>
</property>
</bean>
<bean id="piloteOdilTrigger-1" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="name" value="Trigger 1"/>
<property name="jobDetail" ref="piloteOdilJobBean1"/>
<property name="repeatInterval" value="60000"/>
<property name="group" value="POPO"/>
</bean>
<bean id="piloteOdilTrigger-2" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="name" value="Trigger 2"/>
<property name="jobDetail" ref="piloteOdilJobBean2"/>
<property name="cronExpression" value="${popo.odil.rushhour.cronexpression}" />
<property name="group" value="POPO"/>
</bean>
<bean id="piloteOdilTrigger-3" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="name" value="Trigger 3"/>
<property name="jobDetail" ref="piloteOdilJobBean3"/>
<property name="cronExpression" value="${popo.odil.rushhour.cronexpression}" />
<property name="group" value="POPO"/>
</bean>
<bean id="piloteOdilTrigger-4" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="name" value="Trigger 4"/>
<property name="jobDetail" ref="piloteOdilJobBean4"/>
<property name="cronExpression" value="${popo.odil.rushhour.cronexpression}" />
<property name="group" value="POPO"/>
</bean>
<bean id="piloteOdilTrigger-5" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="name" value="Trigger 5"/>
<property name="jobDetail" ref="piloteOdilJobBean5"/>
<property name="cronExpression" value="${popo.odil.rushhour.cronexpression}" />
<property name="group" value="POPO"/>
</bean>
<bean id="piloteOdilTrigger-6" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="name" value="Trigger 6"/>
<property name="jobDetail" ref="piloteOdilJobBean6"/>
<property name="cronExpression" value="${popo.odil.rushhour.cronexpression}" />
<property name="group" value="POPO"/>
</bean>
<bean id="piloteOdilJobBean-template" abstract="true"
class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="name" value="Pilote ODIL"/>
<property name="jobClass" value="fr.xxxx.popo.batch.PiloteOdilJob"/> <!-- implements StatefulJob -->
<property name="requestsRecovery" value="true"/>
<property name="group" value="POPO"/>
</bean>
<bean id="piloteOdilJobBean1" parent="piloteOdilJobBean-template" />
<bean id="piloteOdilJobBean2" parent="piloteOdilJobBean-template" />
<bean id="piloteOdilJobBean3" parent="piloteOdilJobBean-template" />
<bean id="piloteOdilJobBean4" parent="piloteOdilJobBean-template" />
<bean id="piloteOdilJobBean5" parent="piloteOdilJobBean-template" />
<bean id="piloteOdilJobBean6" parent="piloteOdilJobBean-template" />
this is it's configuration file
#============================================================================
# Main Scheduler Properties
#============================================================================
org.quartz.scheduler.instanceName = OdilScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
#============================================================================
# ThreadPool
#============================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 6
org.quartz.threadPool.threadPriority = 5
#============================================================================
# JobStore
#============================================================================
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
org.quartz.jobStore.misfireThreshold = 3
#============================================================================
# Plugins
#============================================================================
org.quartz.plugin.shutdownhook.class = org.quartz.plugins.management.ShutdownHookPlugin
org.quartz.plugin.shutdownhook.cleanShutdown = true
From what I understood using a ramJobStore make it non clusterable and thus load balancing should not work.
But in reallity when I have 2 servers running, each one has it's own OdilScheduler, with 6 triggers each.
However a total of only 6 trigger will work at the same time.
3 on instance 1 and 3 on instance 2 for example, I want all the 12 trigger to work simultaniously.
What am I missing?
Thanks
ps : quartz version : 1.8.5
I was mislead, in fact I only tried with 3 trigger on each instance.
1 normal and 2 cron trigger.
The cron trigger were using the RAMJobStore, but because of the template, each trigger had the same name so each instance could only use 1 cron trigger (they are identified by their name).
Which is why it looked like load balancing was happening, in fact what was happening is that since they had the same name only one trigger was triggered per instance.
If I had set 5 cron trigger for each instance I would have had only 1 trigger per instance.

How to invoke sftp:outbound-gateway from spring batch?

I would like to invoke sftp:outbound-gateway from batch tasklet in order to download a file from sftp server.
I've seen other posts related to this subject but I'm not sure what am I doing wrong. Could anybody give me a hint based on my configuration? My batch works so the problem is just to ivoke the sftp component in batch step. I've marked the Spring Integration section with comment so it is easier to read just a relevant configuration.
I can see in my logs: DEBUG [o.s.i.e.SourcePollingChannelAdapter] Received no Message during the poll, returning 'false'. So I am not receiving a file but why?
Thanks in advance for your time spend on analysis!
<bean id="ftsSftpClientFactory" class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<property name="host" value="${my.import.sftp.localhost}"/>
<property name="user" value="${my.import.sftp.username}"/>
<property name="password" value="${my.import.sftp.passwort}"/>
</bean>
<!-- Start: Spring Integration -->
<int:channel id="replyChannel" >
<int:queue/>
</int:channel>
<int:channel id="requestChannel" />
<int-sftp:outbound-gateway id="sftpGateway"
session-factory="ftsSftpClientFactory"
request-channel="requestChannel"
reply-channel="replyChannel"
auto-startup="true"
command="get"
command-options="-P"
expression="payload"
remote-directory="."
local-directory="${my.import.sftp.copy.file.destinationpath}">
</int-sftp:outbound-gateway>
<bean name="copyFileTasklet" class="com.mydomain.CopyFileTasklet">
<property name="channel" ref="replyChannel" />
<property name="pollableChannel" ref="requestChannel" />
</bean>
<!-- Start: Spring Batch -->
<bean name="myImportTask" class="com.mydomain.MyImportTask">
<property name="job" ref="unternehmungImportJob"/>
<property name="jobLauncher" ref="jobLauncher"/>
</bean>
<bean id="jobDetail"
class="com.mydomain.MyImportJob">
<property name="myImportTask" ref="myImportTask" />
</bean>
<!--suppress SpringBatchModel -->
<batch:job id="myImportJob">
<batch:step id="copy-file-step" next="my-import-step">
<batch:tasklet ref="copyFileTasklet"/>
</batch:step>
<batch:step id="my-import-step">
<batch:tasklet>
<batch:chunk reader="myItemReader"
writer="myItemWriter"
commit-interval="10000">
<!--
skip-limit="10000"
<batch:skippable-exception-classes>
<batch:include class="java.lang.Exception"/>
<batch:exclude class="java.io.FileNotFoundException"/>
</batch:skippable-exception-classes> -->
</batch:chunk>
<batch:transaction-attributes isolation="DEFAULT" propagation="REQUIRED"/>
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="myItemReader" scope="step" class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="linesToSkip" value="1"/>
<property name="encoding" value="${my.import.batch.encoding}" />
<property name="resource" value="${my.import.batch.input.resource}"/>
<property name="lineMapper">
<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="lineTokenizer" ref="lineTokenizer"/>
<property name="fieldSetMapper">
<bean class="com.mydomain.MyImportMapper"/>
</property>
</bean>
</property>
</bean>
<bean id="myItemWriter" class="com.mydomain.MyItemWriter">
<property name="myApplicationService" ref="defaultmyApplicationService" />
</bean>
<bean id="lineTokenizer" class="com.mydomain.DelimitedLineTokenizerWithEOF">
<property name="delimiter" value="${my.import.batch.delimiter}" />
<property name="eofMarker" value="${my.import.batch.eof.marker}" />
</bean>
public class CopyFileTasklet implements Tasklet {
private MessageChannel requestChannel;
private PollableChannel replyChannel;
public void setRequestChannel(MessageChannel requestChannel) {
this.requestChannel = requestChannel;
}
public void setReplyChannel(PollableChannel replyChannel) {
this.replyChannel = replyChannel;
}
#Override
public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
Message<?> result = replyChannel.receive(10000);
Object file = result.getPayload();
return RepeatStatus.FINISHED;
}
}
Your issue that you don't inititate Integration Flow from your custom Tasklet. Of course you can't receive anything from the replyChannel, if you haven't sent request before.
If you just need to process Integration Flow and get result from it, it would be better to use POJI <gateway> from that Tasklet:
public interface SftpGateway {
File download(String fileName);
}
<gateway id="sftpGateway" service-interface="com.my.proj.SftpGateway"
default-request-channel="requestChannel"/>
<bean name="copyFileTasklet" class="com.mydomain.CopyFileTasklet">
<property name="sftpGateway" ref="sftpGateway" />
</bean>
Something like that.