Quartz scheduler not scheduling/firing the jobs - spring

I try to schedule a quartz scheduler with spring-4.3.27 and quartz-2.3.2 with xml based configuration, Jobs are not getting fired.
Earlier its working quartz-2.1.1 and quartz-all-2.1.1, Now I migrated to quartz-2.3.2 (Quratz-all-2.3.2 which is not available), But the jobs are not getting triggered.
my Quartz Scheduler Configuration like,
<task:annotation-driven />
<!-- enable this for websphere -->
<bean name="workManagerTaskExecutor"
class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor">
<property name="resourceRef" value="true" />
<property name="workManagerName" value="wm/default" />
</bean>
<bean name="quartzScheduler"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="taskExecutor" ref="workManagerTaskExecutor" />
<property name="autoStartup" value="true" />
<property name="nonTransactionalDataSource" ref="dataSource" />
<!-- <property name="transactionManager" ref="transactionManager" /> -->
<property name="quartzProperties">
<util:properties location="classpath:/quartz.properties" />
</property>
<property name="waitForJobsToCompleteOnShutdown" value="true" />
<property name="jobDetails">
<list>
<ref bean="Job1" />
</list>
</property>
<property name="triggers">
<list>
<ref bean="jobTrigger" />
</list>
</property>
<property name="schedulerContextAsMap">
<map>
<entry key="messageExchangeLogDAO" value-ref="MessageExchangeLogDAO" />
<entry key="outboundMessageSender" value-ref="outboundMessageSender" />
<entry key="marshaller" value-ref="marshaller" />
<entry key="reportService" value-ref="reportService" />
<entry key="userDao" value-ref="UserDAO" />
<entry key="jobService" value-ref="jobService" />
<entry key="purchaseOrderDAO" value-ref="PurchaseOrderDAO" />
<entry key="dbConfig" value-ref="databaseConfiguration" />
<entry key="purchaseOrderService" value-ref="purchaseOrderService" />
<entry key="userRoleDAO" value-ref="userRoleDAO" />
<entry key="mailService" value-ref="mailService" />
<entry key="buyerNotificationService" value-ref="buyerNotificationService" />
<entry key="supplierNotificationService" value-ref="supplierNotificationService" />
<entry key="adminNotificationService" value-ref="adminNotificationService" />
<entry key="messageService" value-ref="messageService" />
<entry key="messageProcessor" value-ref="messageProcessor" />
<entry key="em" value-ref="entityManagerFactory"/>
<entry key="invoiceService" value-ref="invoiceService" />
<entry key="approvedInvoiceDAO" value-ref="ApprovedInvoiceDAO" />
</map>
</property>
</bean>
<bean
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<bean id="jobTrigger"
class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
<property name="jobDetail" ref="job1" />
<property name="startDelay" value="0" />
<property name="repeatInterval" value="300000" />
</bean>
<bean name="job1"
class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.jobs.scheduleJob" />
</bean>
<aop:config>
<aop:pointcut id="quartzSchedulerPointcut"
expression="execution(* org.quartz.Scheduler.*(..))" />
<aop:advisor advice-ref="quartzSchedulerAdvice"
pointcut-ref="quartzSchedulerPointcut" />
</aop:config>
<tx:advice id="quartzSchedulerAdvice">
<tx:attributes>
<tx:method name="get*" read-only="true" propagation="SUPPORTS" />
<tx:method name="set*" read-only="true" propagation="SUPPORTS" />
<tx:method name="is*" read-only="true" propagation="SUPPORTS" />
<tx:method name="insert*" read-only="false" propagation="REQUIRED" />
<tx:method name="update*" read-only="false" propagation="REQUIRED" />
<tx:method name="delete*" read-only="false" propagation="REQUIRED" />
<tx:method name="schedule*" read-only="false" propagation="REQUIRED" />
<tx:method name="pause*" read-only="false" propagation="REQUIRED" />
<tx:method name="resume*" read-only="false" propagation="REQUIRED" />
<tx:method name="run*" read-only="false" propagation="REQUIRED" />
<tx:method name="update*" read-only="false" propagation="REQUIRED" />
<tx:method name="delete*" read-only="false" propagation="REQUIRED" />
<tx:method name="toggle*" read-only="false" propagation="REQUIRED" />
<tx:method name="clone*" read-only="false" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
Quartz.properies:
org.quartz.scheduler.instanceName = TSPScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.class = org.springframework.scheduling.quartz.LocalDataSourceJobStore
org.quartz.jobStore.useProperties=true
org.quartz.jobStore.clusterCheckinInterval=1000
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.misfireThreshold = 10000
org.quartz.jobStore.selectWithLockSQL = SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE
org.quartz.jobStore.dontSetAutoCommitFalse = false
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 15
org.quartz.threadPool.threadPriority = 15
org.quartz.jobStore.isClustered = true
Logs:
org.springframework.scheduling.quartz.SchedulerFactoryBean startScheduler Starting Quartz Scheduler now
org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor finishRegistration **No TaskScheduler/ScheduledExecutorService bean found for scheduled processing**
After that No error and nothing is getting printed in the Logs, at the same time jobs also not getting fired.
In the QUARTZ_TRIGGERS table next_fire_time alone getting updated based fire interval.
Note: The same configuration working fine with quartz-2.1.1 and quartz-all-2.1.1, Not working with quartz-2.3.2
anyone guide me where I did mistake? what I need to do here to resolve this scheduling issue?

sched_time column is missing in qrtz_fired_triggers table. After adding that column its started firing.

There are lots of differences between the tables from 1.x to 2.x. We recently migrated from 1.x and created all tables before deploying the application.

Related

Message Driven Adapter and external transaction manager (Atomikos)

I have message-driven-channel-adapter configured that picks the message from queue and sends down stream for processing . service-activator down stream will process this message have some database inserts using spring-jpa and also putting message in queue. As Atomikos is used as transaction manager if any exception is thrown in service-activator the exception message is sent to messageError channel that is configured on message-driven-channel-adapter. I am not able to log this message in to database as I am getting com.atomikos.jdbc.AtomikosSQLException: Transaction is marked for rollback only or has timed out. How to handle the exception message. I am using spring integration 4.2.4.RELEASE. Below is my configuration
<context:annotation-config />
<context:component-scan
base-package="com.home.sendermain,com.home.queueapi,com.home.processauth" />
<int-jms:message-driven-channel-adapter
id="pollQueuetoProcess" channel="queueChannel" destination="senderQueue"
concurrent-consumers="5" max-concurrent-consumers="10" acknowledge="transacted"
auto-startup="false" error-channel="messageError" transaction-manager="JtaTransactionManager" />
<int:recipient-list-router id="status1router"
input-channel="queueChannel" default-output-channel="nullChannel">
<int:recipient channel="messageSuccessChannel"
selector-expression="payload.getStatus1()==1" />
</int:recipient-list-router>
<int:channel id="processChannel"></int:channel>
<int:chain id="messageSuccessChain" input-channel="messageSuccessChannel">
<int:service-activator ref="senderMessageProcess" id="check1"
method="check1" requires-reply="true" />
<int:service-activator ref="senderMessageProcess"
id="processMessageStatus" method="processMessageStatus"
requires-reply="true" />
<int:recipient-list-router id="status2router"
default-output-channel="nullChannel">
<int:recipient channel="nullChannel"
selector-expression="payload.getStatus2()==8" />
<int:recipient channel="processChannel"
selector-expression="payload.getStatus2()==5 || payload.getStatus2()==10" />
</int:recipient-list-router>
</int:chain>
<int:service-activator input-channel="processChannel"
output-channel="nullChannel" ref="senderMessageProcess" id="processMessage"
method="processMessage" requires-reply="true" />
<int:service-activator ref="senderErrorProcess"
id="processErrorMessage" method="processErrorMessage" input-channel="messageError"
output-channel="nullChannel" requires-reply="true" />
<bean id="senderQueue" class="com.ibm.mq.jms.MQQueue">
<constructor-arg value="SENDERQUEUE" />
</bean>
<bean id="testQ" class="com.ibm.mq.jms.MQQueue">
<constructor-arg value="TESTQUEUE" />
</bean>
<!-- declaring MQ XA connection with max pool size as 10 -->
<bean id="mqConnectionFactory" class="com.ibm.mq.jms.MQXAQueueConnectionFactory">
<property name="queueManager">
<value>TESTQMGR</value>
</property>
</bean>
<bean id="connectionFactory" class="com.atomikos.jms.AtomikosConnectionFactoryBean"
init-method="init" destroy-method="close">
<property name="uniqueResourceName" value="ALL_MQSeries_XA_RMI" />
<property name="xaConnectionFactory" ref="mqConnectionFactory" />
<property name="maxPoolSize">
<value>10</value>
</property>
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<property name="explicitQosEnabled" value="true" />
<property name="sessionTransacted" value="true" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
depends-on="JtaTransactionManager, springJtaPlatformAdapter">
<property name="packagesToScan"
value="com.home.domain.entity.processentities" />
<property name="dataSource" ref="datasource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="mappingResources">
<value>META-INF/orm.xml</value>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.Oracle10gDialect
</prop>
<prop key="hibernate.max_fetch_depth">3</prop>
<prop key="hibernate.jdbc.fetch_size">50</prop>
<prop key="hibernate.jdbc.batch_size">10</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="jadira.usertype.autoRegisterUserTypes">true</prop>
<prop key="jadira.usertype.databaseZone">jvm</prop>
<prop key="jadira.usertype.javaZone">jvm</prop>
<prop key="hibernate.transaction.jta.platform">com.home.AtomikosJtaPlatform</prop>
<prop key="javax.persistence.transactionType">JTA</prop>
</props>
</property>
</bean>
<jpa:repositories base-package="com.home.domain.repository.processrepository"
entity-manager-factory-ref="entityManagerFactory"
transaction-manager-ref="JtaTransactionManager" />
<jpa:auditing />
<aop:config>
<aop:pointcut id="serviceOperation"
expression="execution(* com.home.sendermain.service.*.*(..)) || execution(* com.home.sendermain.error.*.*(..))" />
<aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="JtaTransactionManager">
<tx:attributes>
<tx:method name="find*" read-only="true" rollback-for="java.lang.Throwable" />
<tx:method name="count*" propagation="NEVER" rollback-for="java.lang.Throwable" />
<tx:method name="*" rollback-for="java.lang.Throwable" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="serviceOperationQueue"
expression="execution(* com.home.queueapi.*.*(..))" />
<aop:advisor pointcut-ref="serviceOperationQueue"
advice-ref="txAdviceQueue" />
</aop:config>
<tx:advice id="txAdviceQueue" transaction-manager="JtaTransactionManager">
<tx:attributes>
<tx:method name="find*" read-only="true" rollback-for="java.lang.Throwable" />
<tx:method name="count*" propagation="NEVER" rollback-for="java.lang.Throwable" />
<tx:method name="*" rollback-for="java.lang.Throwable" />
</tx:attributes>
</tx:advice>
<bean id="userTransactionService" class="com.atomikos.icatch.config.UserTransactionServiceImp"
init-method="init" destroy-method="shutdownForce">
<constructor-arg>
<!-- IMPORTANT: specify all Atomikos properties here -->
<props>
<prop key="com.atomikos.icatch.service">
com.atomikos.icatch.standalone.UserTransactionServiceFactory
</prop>
</props>
</constructor-arg>
</bean>
<!-- Construct Atomikos UserTransactionManager, needed to configure Spring -->
<bean id="AtomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close" depends-on="userTransactionService">
<!-- IMPORTANT: disable startup because the userTransactionService above
does this -->
<property name="startupTransactionService" value="false" />
<!-- when close is called, should we force transactions to terminate or
not? -->
<property name="forceShutdown" value="false" />
</bean>
<!-- Also use Atomikos UserTransactionImp, needed to configure Spring -->
<bean id="AtomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"
depends-on="userTransactionService">
<property name="transactionTimeout" value="300" />
</bean>
<!-- Configure the Spring framework to use JTA transactions from Atomikos -->
<bean id="JtaTransactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager"
depends-on="userTransactionService">
<property name="transactionManager" ref="AtomikosTransactionManager" />
<property name="userTransaction" ref="AtomikosUserTransaction" />
</bean>
<!-- declaring database connection for xaresource with poolsize is set to
10 -->
<bean id="datasource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
init-method="init" destroy-method="close">
<property name="uniqueResourceName">
<value>XAORADBMS</value>
</property>
<property name="xaDataSourceClassName">
<value>${jdbc.driverClassName}</value>
</property>
<property name="xaProperties">
<props>
<prop key="user">${jdbc.username}</prop>
<prop key="password">${jdbc.password}</prop>
<prop key="URL">${jdbc.url}</prop>
</props>
</property>
<property name="poolSize">
<value>${sender.maxPoolSize}</value>
</property>
</bean>
<bean id="springJtaPlatformAdapter" class="com.home.AtomikosJtaPlatform">
<property name="jtaTransactionManager" ref="JtaTransactionManager" />
</bean>
Suggest how to handle exception message .
You need to start a new transaction for the log process - possibly with a simple DB Tx Manager - not Atomikos - see Propagation.REQUIRES_NEW.

Spring-Batch MongoDB : Skip functionality is not working properly in MongoItemReader scenario

Skip exception class functionality is not working properly when MongoItemreader is being used.
Issues:
1. Spring batch is stuck at a particular data row (in my case 15). It calls MessageContextReadConverter and onReadError for same row number 15 -- 3 times.
2. skiplistener is never invoked.
Scenario:
Suppose 20 rows are fetched from MongoDB and at row number 15 configurable exception ".ConversionFailedException" is thrown from a custom class derived from Converter, (MessageContextReadConverter implements Converter)
. MessageContextReadConverter is set during mongoTemplate creation,.
Now, exception thrown at row number 15 is received in custom readlistener (public void onReadError(Exception ex)).
Configuration XML:
<context:property-placeholder location="classpath:application.properties" />
<context:component-scan base-package="com.XXX.YYY.batch.kernel" />
<context:component-scan base-package="com.XXX.YYY.batch.dao" />
<context:annotation-config />
<!-- Enable Annotation based Declarative Transaction Management -->
<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager" />
<!-- Creating TransactionManager Bean, since JDBC we are creating of type DataSourceTransactionManager -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<batch:job id="txnLogJob" restartable="false">
<batch:step id="txnload">
<tasklet allow-start-if-complete="true" transaction-manager="transactionManager">
<chunk reader="txnLogReader" processor="txnLogProcessor"
writer="txnLogItemWriter" commit-interval="10" skip-limit="3">
<skippable-exception-classes>
<include class="org.springframework.core.convert.ConversionFailedException" />
</skippable-exception-classes>
</chunk>
<listeners>
<listener ref="stepListener" />
<listener ref="chunklistener" />
<listener ref="readlistener" />
<listener ref="skiplistener" />
</listeners>
</tasklet>
</batch:step>
<batch:listeners>
<batch:listener ref="completionListener" />
</batch:listeners>
</batch:job>
<bean id="txnLogReader" class="org.springframework.batch.item.data.MongoItemReader"
scope="step">
<property name="template" ref="mongoTemplate" />
<property name="query" value=" { }" />
<property name="pageSize" value="50" />
<property name="sort">
<map>
<entry key="audit_info.created_on"
value="#{T(org.springframework.data.domain.Sort.Direction).ASC}" />
</map>
</property>
<property name="collection" value="txnlog" />
<property name="targetType" value="com.XXX.YYY.kernel.msg.MessageContext" />
</bean>
<bean id="completionListener"
class="com.XXX.YYY.batch.listeners.JobCompletionNotificationListener" />
<bean id="stepListener"
class="com.XXX.YYY.batch.listeners.StepExecutionListener" />
<bean id="chunklistener"
class="com.XXX.YYY.batch.listeners.ChunkExecutionListener" />
<bean id="readlistener"
class="com.XXX.YYY.batch.listeners.ReadExecutionListener" />
<bean id="skiplistener"
class="com.XXX.YYY.batch.listeners.SkipExecutionListener" />
<bean id="jobParametersDAOImpl" class="com.XXX.YYY.batch.dao.JobParametersDAOImpl" />
<bean id="batchLoader" class="com.XXX.YYY.batch.kernel.BatchLoader" />
<bean id="batchjobParameter" class="com.XXX.YYY.batch.dao.Batch_Job_Parameters" />
<!-- <bean id="reportWriter" class="org.springframework.batch.item.data.MongoItemWriter">
<property name="template" ref="mongoTemplate" /> <property name="collection"
value="txnlog" /> name of the collection to write </bean> -->
<bean id="txnLogItemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter"
scope="step">
<property name="shouldDeleteIfExists" value="true" />
<property name="resource" value="file:target/test-outputs/output.txt" />
<property name="lineAggregator">
<bean
class="org.springframework.batch.item.file.transform.PassThroughLineAggregator" />
</property>
</bean>
<bean id="txnLogProcessor"
class="com.XXX.YYY.batch.processor.MessageContextItemProcessor" />
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<property name="databaseType" value="MYSQL" />
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="transactionManager" />
</bean>
<bean id="dataSource" class="com.XXX.YYY.common.DataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="connectionProperties" value="${jdbc.connectionProperties}" />
<property name="initialSize" value="${jdbc.initialSize}" />
<property name="maxTotal" value="${jdbc.maxTotal}" />
<property name="maxIdle" value="${jdbc.maxIdle}" />
<property name="minIdle" value="${jdbc.minIdle}" />
<property name="maxWaitMillis" value="${jdbc.maxWaitMillis}" />
<property name="testOnBorrow" value="${jdbc.testOnBorrow}" />
<property name="testWhileIdle" value="${jdbc.testWhileIdle}" />
<property name="testOnReturn" value="${jdbc.testOnReturn}" />
<property name="validationQuery" value="${jdbc.validationQuery}" />
</bean>

SQLRecoverableException: Error de E/S connection abort: recv failed

I have a problem with the connection to the database, after a period of inactivity in the application, I return to enter and send me the following error
01-08-2014 04:45:33 PM org.apache.catalina.core.StandardWrapperValve invoke
GRAVE: Servlet.service() para servlet springapp lanzó excepción
org.springframework.dao.DataAccessResourceFailureException:
### Error querying database. Cause: java.sql.SQLRecoverableException: Error de E/S: Software caused connection abort: recv failed
and this is my oracle data source
<!-- Load properties with PlaceHolder -->
<context:property-placeholder location="WEB-INF/properties/*.properties" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<aop:config>
<!-- aop:advisor pointcut="execution(* *..Service.*(..))" advice-ref="txAdvice"/ -->
<aop:pointcut id="fooServiceOperation" expression="execution(* cl.bbr.proceso.maestro.proceso.ProcesoMaestro.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation"/>
</aop:config>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<!-- all methods starting with 'get','is','select' are read-only -->
<tx:method name="get*" read-only="true"/>
<tx:method name="is*" read-only="true"/>
<tx:method name="select*" read-only="true"/>
<!-- other methods use the default transaction settings (see below) -->
<tx:method name="*" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<tx:advice id="noTxAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRES_NEW" />
</tx:attributes>
</tx:advice>
EDIT 05/08/2014
DATABASE : ORACLE 11G
SPRING VERSION : 3.0
TOMCAT 6.0
hopefully you can help me thanks.
Adding this lines to dataSource bean solved the problem:
<property name="validationQuery" value="SELECT 1 from dual" />
<property name="testOnBorrow" value="true" />
About validation query you can read in the answer for this question: What is a validationQuery with respect to databases and JNDI?
"testOnBorrow" means that before every query execution validationQuery will be executed.

Choose between muliple transaction managers at runtime

I have 2 clients using same Spring based REST Application deployed in tomcat. Depending on client I need to choose between data sources and transaction manager. How do I choose at runtime, which transaction manager to use?
<bean id="First_dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="url" value="${First_jdbc.url}" />
<property name="driverClassName" value="${First_jdbc.driverClassName}" />
<property name="username" value="${First_jdbc.username}" />
<property name="password" value="${First_jdbc.password}" />
<property name="removeAbandoned" value="true" />
<property name="initialSize" value="20" />
<property name="maxActive" value="30" />
<!-- <property name="defaultAutoCommit" value="false" /> -->
</bean>
<bean id="Second_dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="url" value="${Second_jdbc.url}" />
<property name="driverClassName" value="${Second_jdbc.driverClassName}" />
<property name="username" value="${Second_jdbc.username}" />
<property name="password" value="${Second_jdbc.password}" />
<property name="removeAbandoned" value="true" />
<property name="initialSize" value="20" />
<property name="maxActive" value="30" />
<!-- <property name="defaultAutoCommit" value="false" /> -->
</bean>
<bean id="First_TransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
scope="singleton">
<property name="dataSource" ref="First_dataSource" />
<qualifier value="SC_TM"></qualifier>
</bean>
<bean id="Second_TransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
scope="singleton">
<property name="dataSource" ref="Second_dataSource" />
<qualifier value="Second_TM"></qualifier>
</bean>
In code how do choose #Transactional("????") at run time.
If it is not possible with org.springframework.jdbc.datasource.DataSourceTransactionManager is there any other way of doing it?
Using #Transactional, you can specify the transaction manager like this:
#Transactional("First_TransactionManager")
or
#Transactional("Second_TransactionManager")
depending on which one you want to use. Make sure to use inside the transactional method the correct Entity Manager / session factory. Those you also have to specify which one you want to inject with #PersistenceContext("nameOfPersistenceUnit").
I do not know why you want to change between the 2 transaction manager may be you need to check Transaction manager chain solution, but in case you need this you can add your #transactional on Repo methods and do 2 Repos and manage it from the service layer as switch, otherwise I'm believing that there is solution could be done using AOP but it will need more time to think about it.
Problem is solved through AOP.
Define multiple data sources and corresponding Transacation Manager (as I have shown in my
base question)
First_dataSource mapped with First_TransactionManager and Second_dataSource mapped with Second_TransactionManager
Select which data source to use programatically depending on your business rules. In my case it was orgId
public class DataSourceProvider {
#Autowired
DataSource First_dataSource;
#Autowired
DataSource Second_dataSource;
public DataSource getDataSource(int orgId) {
if (orgId == Constants.BUSINESS_PARTY_1)
return Second_dataSource;
else
return First_dataSource;
}
public DataSource getFirst_dataSource() {
return First_dataSource;
}
public void setFirst_dataSource(DataSource First_dataSource) {
First_dataSource = First_dataSource;
}
public DataSource getSecond_dataSource() {
return Second_dataSource;
}
public void setSecond_dataSource(DataSource Second_dataSource) {
Second_dataSource = Second_dataSource;
}
}
AOP Configuration:
<tx:advice id="First_txAdvice" transaction-manager="First_TransactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="First_daoimplOperation"
expression="execution(* in.company.common.service.CommonServiceImpl.*(..))" />
<aop:advisor advice-ref="First_txAdvice" pointcut-ref="First_daoimplOperation" />
</aop:config>
<tx:advice id="Second_txAdvice" transaction-manager="Second_TransactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="Second_daoimplOperation"
expression="execution(* in.company.common.service.CommonServiceImpl.*(..))" />
<aop:advisor advice-ref="Second_txAdvice" pointcut-ref="Second_daoimplOperation" />
</aop:config>
all database related services should be in matching pointcut like in this case it is: in.company.common.service.CommonServiceImpl.*(..))
Consider using the Spring provided AbstractRoutingDataSource instead of going down the path of choosing between multiple transaction managers. It will be a much cleaner solution.
See my answer to a similar question here :
https://stackoverflow.com/a/44167079/2200690

Apply Transaction Management Spring

I have a j2ee application running on spring framework. I am trying to apply transaction management using aop but apparently it won't work. I am trying to apply transaction to a function from a class named RegisterBLogic with function name execute(ParamObject obj). My function inserts into a database. I also put a throw ne Exception my function to force the throwing of exception.
Inside userManagerContext:
<bean id="RegisterBLogic"
scope="singleton"
class="jp.co.anicom.fw.web.usermanager.blogic.RegisterBLogic">
<property name="queryDAO"
ref="queryDAO" /> <property
name="updateDAO" ref="updateDAO" />
</bean>
Inside ApplicationContext
<bean id="TerasolunaDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="PrototypeDataSource" />
</bean>
<tx:advice id="transactionInterceptor" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="insert*" propagation="REQUIRED"
rollback-for="java.lang.Exception" />
<tx:method name="execute*" propagation="REQUIRED"
rollback-for="java.lang.Exception" />
<tx:method name="*" propagation="REQUIRED" read-only="true" />
</tx:attributes>
</tx:advice>
<!-- AOPの設定 -->
<aop:config>
<aop:pointcut id="blogicBeans" expression="bean(*BLogic)" />
<aop:pointcut id="serviceBeans" expression="bean(*Service)" />
<aop:advisor pointcut-ref="blogicBeans" advice-ref="transactionInterceptor" />
<aop:advisor pointcut-ref="serviceBeans" advice-ref="transactionInterceptor" />
</aop:config>
Yeah these beans already exist. I have this bean declaration under userManagerCOntext.xml. This xml is loaded in the struts config through
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation"
value="/WEB-INF/userManager/userManagerContext.xml"/>
</plug-in>
I found the problem. Currently i am using a data source from a JNDI.
class="org.springframework.jndi.JndiObjectFactoryBean">
i changed it to normal data source with property defaultAutoCommit set to false
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName"
value="oracle.jdbc.OracleDriver" />
<property name="url"
value="jdbc:oracle:thin:#192.168.178.82:1521:anicom" />
<property name="username" value="jay" />
<property name="password" value="jay" />
<property name="initialSize" value="5" />
<property name="maxActive" value="10" />
<property name="defaultAutoCommit" value="false" />
</bean>
How do I use JNDI data source but be able to set a property somewhat similar to defaultAutoCommit to false. I am using Oracle weblogic server and my data source is stored in it accessed through JNDI
First of all, this XML is malformed (should be </tx:advice>).
Are the beans you want to wrap in AOP already present when this configuration is processed?

Resources