I have a scheduled timer task which is managed by Spring container. I can't figure a way to kill it once it throws some exception say RuntimeException. It keeps running for ever. Is there a way to access the Timer object and cancel it from the code?
This is my code:
<bean id="myTimer" class="com.aspect.MyTimer"></bean>
<bean id="timerTaskFactoryBean"
class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean">
<property name="targetObject" ref="myTimer"></property>
<property name="targetMethod" value="doSomething"></property>
</bean>
<bean id="timerTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="timerTask" ref="timerTaskFactoryBean"></property>
<property name="period" value="5000"></property>
</bean>
<bean class="org.springframework.scheduling.timer.TimerFactoryBean" id="timerBean">
<property name="scheduledTimerTasks">
<list>
<ref local="timerTask"></ref>
</list>
</property>
</bean>
Java class
public class MyTimer {
public void doSomething(){
System.out.println("I am running...");
try{
throw new RuntimeException();
}
catch(RuntimeException e){
ScheduledTimerTask timer = (ScheduledTimerTask) App.appContext.getBeanFactory().getBean("timerTask");
timer.getTimerTask().cancel();
System.out.println("Timer cancelled due to..." +e);
}
}
}
I guess you need to access the bean through the container and cancel it.
Related
here is my 'GenericQuartzJob' class
public class GenericQuartzJob extends QuartzJobBean
{
private String batchProcessorName;
public String getBatchProcessorName() {
return batchProcessorName;
}
public void setBatchProcessorName(String name) {
// System.out.println("jo"+name);
this.batchProcessorName = name;
}
protected void executeInternal(JobExecutionContext jobCtx) throws JobExecutionException
{
try {
// System.out.println("jo");
SchedulerContext schedCtx = jobCtx.getScheduler().getContext();
ApplicationContext appCtx =
(ApplicationContext) schedCtx.get("applicationContext");
java.lang.Runnable proc = (java.lang.Runnable) appCtx.getBean(batchProcessorName);
proc.run();
}
catch (Exception ex) {
// ex.printStackTrace();
throw new JobExecutionException("Unable to execute batch job: " + batchProcessorName, ex);
}
}
}
Here is my MyRunnableJob Class
#Configuration
#ComponentScan("com.ehydromet.service")
public class MyRunnableJob implements Runnable {
//#Resource private SpringService myService;
#Autowired
public UserService service;
#Override
public void run() {
// System.out.println("hu");
try{
service.getAllAdminUser();
}catch(Exception ex){
System.out.println(ex.getMessage()+" MyRunnableJob");
}MqttImplement mqtt=new MqttImplement();
mqtt.publishMessage();
//Run the Job. This code will run in the Spring context so you can use injected dependencies here.
}
}
Below is my MqttImplement class
public class MqttImplement implements MqttCallback {
#Autowired
private static UserService service;
#RequestMapping("/publish")
public void publishData(ModelMap map){
MyTask.map=map;
pubTopic="tmsdata";
susTopic="tmsack";
if(initializeMqTTParameters() ){
if(suscribeForAck()){
// new ClassPathXmlApplicationContext("spring-quartz.xml");
AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
}
}
// initializeMqTTParameters();
// suscribeForAck();
// publishMessage();
}
public void publishMessage(){
try{
// System.out.print("sending ");
Received received=service.getReceivedDataToPublishTMS();
if(received!=null){
System.out.print("sending you not null");
String publisgMSG=createMessageToPublish(received);
pubMessage="lava," ;
publishMessageTms();
}else{
System.out.println("null hora");
}
}catch(Exception ex){
System.out.println("hora"+ex.getLocalizedMessage()+" "+ex.toString());
}
}
}
and here is xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- <bean id="exampleBusinessObject" class="com.ehydromet"/> -->
<!-- Old JobDetail Definition
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="exampleBusinessObject"/>
<property name="targetMethod" value="doIt"/>
</bean>
-->
<!-- Runnable Job: this will be used to call my actual job. Must implement runnable -->
<bean name="myRunnableJob" class="com.ehydromet.controller.MyRunnableJob"></bean>
<!-- New Clusterable Definition -->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.ehydromet.schedule.GenericQuartzJob" />
<property name="jobDataAsMap">
<map>
<entry key="batchProcessorName" value="myRunnableJob" />
</map>
</property>
</bean>
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<!-- see the example of method invoking job above -->
<property name="jobDetail" ref="jobDetail"/>
<!-- 10 seconds -->
<property name="startDelay" value="5000"/>
<!-- repeat every 50 seconds -->
<property name="repeatInterval" value="5000"/>
</bean>
<context:component-scan base-package="com.ehydromet.service"/>
<context:component-scan base-package="com.ehydromet.dao"/>
<context:component-scan base-package="com.ehydromet.service.impl"/>
<context:component-scan base-package="com.ehydromet.dao.impl"/>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.ehydromet.entity.Alarms</value>
<value>com.ehydromet.entity.UserData</value>
<value>com.ehydromet.entity.ModemInfo</value>
<value>com.ehydromet.entity.Received</value>
<value>com.ehydromet.entity.Modems</value>
<value>com.ehydromet.entity.AdminLogin</value>
<value>com.ehydromet.entity.UserPolicy</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
</props>
</property>
</bean>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
<property name="triggers">
<list>
<ref bean="simpleTrigger" />
</list>
</property>
<!-- Add this to make the Spring Context Available -->
<property name="applicationContextSchedulerContextKey"><value>applicationContext</value></property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/ejava" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="hibernateInterceptor" class="org.springframework.orm.hibernate3.HibernateInterceptor">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
</beans>
Dao classes are #Transactional and #Repository.
in MqttImplement class service object is null i think autowired is not working with Quartz scheduler. Any suggestion????
i think autowired is kind of resolved. but
error is-- org.springframework.beans.NotWritablePropertyException: Invalid property 'sessionFactory' of bean class [org.springframework.scheduling.quartz.SchedulerFactoryBean]: Bean property 'sessionFactory' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
i am new to it. so may be some foolish mistakes i have done, please have a look.
Have you tried #Autowired without static? Seems weird for me...
From other side you do this:
MqttImplement mqttPublishTms=new MqttImplement();
................
mqttPublishTms.publishMessage();
So, it's new not Dependency Injection. There is no surprise that the service property there is null.
I have following Thread and transactional method, I have get thrown an exception to test rollback of insertion of DB but notthing is changed. What am I missing?
public class CleaningThread extends Thread {
public void run() {
try {
doJob();
} catch (Exception e) {
e.printStackTrace();
}
}
#Transactional(rollbackFor=Exception.class)
private void doJob() throws Exception {
//INSERT OPERATION
final BatchSqlUpdate bs = new BatchSqlUpdate
bs.flush()
throw new Exception("Custom exception")
//UPDATE
}
}
Application Context:
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>file:conf/offclear.properties</value>
</list>
</property>
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
</bean>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="cleaningThread" class="CleaningThread" scope="prototype"/>
Using Spring 3.1
You're invoking method doJob() from method run() of the same class. That's why you're working with real method, not proxied one.
Actually, this question was covered in this topic: One Service method invoke inner multiple method for Spring transaction
My acitvemq server always print error below :
2014-07-12 16:14:27,820 | ERROR | Could not accept connection :
org.apache.activemq.transport.tcp.ExceededMaximumConnectionsException:
Exceeded the maximum number of allowed client connections.
See the 'maximumConnections' property on the TCP transport configuration URI
in the ActiveMQ configuration file (e.g., activemq.xml)
| org.apache.activemq.broker.TransportConnector
| ActiveMQ Transport Server Thread Handler:
tcp://0.0.0.0:61616?maximumConnections=1000&wireformat.maxFrameSize=104857600
When I restart the server it will be ok. But after a few days the error come out again.
I don't why the connections always increase to 1000.
My server config:
<!-- activeMQ -->
<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="${jms.brokerURL}"></property>
</bean>
<!-- Spring Caching -->
<bean id="cachingConnectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="jmsConnectionFactory" />
<property name="sessionCacheSize" value="10" />
</bean>
<!-- Spring JMS Template -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="cachingConnectionFactory" />
<property name="explicitQosEnabled" value="true" />
<property name="priority" value="4" />
</bean>
<bean id="scoreQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="SCORE" />
</bean>
<bean id="scoreMessage" class="com.tt.score.mq.server.ScoreMessage"></bean>
<bean id="scoreListener"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsConnectionFactory"></property>
<property name="destination" ref="scoreQueue"></property>
<property name="messageListener" ref="scoreMessage"></property>
<property name="concurrentConsumers" value="10" />
<property name="maxConcurrentConsumers" value="100" />
<property name="sessionAcknowledgeModeName" value="CLIENT_ACKNOWLEDGE" />
</bean>
My client config xml:
<!-- Spring Caching -->
<bean id="cachingConnectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="jmsConnectionFactory" />
<property name="sessionCacheSize" value="10" />
</bean>
<!-- Spring JMS Template -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="cachingConnectionFactory" />
<property name="explicitQosEnabled" value="true" />
<property name="priority" value="4" />
</bean>
<bean id="messageProducer" class="com.tt.score.mq.client.MessageProducer">
<property name="jmsTemplate" ref="jmsTemplate" />
<property name="scoreQueue" ref="scoreQueue" />
</bean>
<bean id="scoreQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="SCORE" />
</bean>
Other info:
acitvemq server : 5.8.0
client acitvemq : 5.4.2
spring : 3.0.7
spring-jms : 3.0.7
We use transactionManager so the DefaultMessageListenerContainer's cachelevel will be set to none.
---update add dao config----------------------------------
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName"><value>${jdbc.driverClass}</value></property>
<property name="username"><value>${jdbc.user}</value></property>
<property name="url"><value>${jdbc.jdbcUrl}</value></property>
<property name="password">
<bean class="com.tongbanjie.commons.util.EncryptDBPasswordFactory">
<property name="password" value="${jdbc.password}" />
</bean>
</property>
<property name="maxActive"><value>${jdbc.maxActive}</value></property>
<property name="initialSize"><value>${jdbc.initialSize}</value></property>
<property name="maxWait"><value>60000</value></property>
<property name="maxIdle"><value>${jdbc.maxIdle}</value></property>
<property name="minIdle"><value>5</value></property>
<property name="removeAbandoned"><value>true</value></property>
<property name="removeAbandonedTimeout"><value>180</value></property>
<property name="timeBetweenEvictionRunsMillis"><value>60000</value></property>
<property name="minEvictableIdleTimeMillis"><value>1800000</value></property>
<property name="defaultAutoCommit" value="false" />
<property name="connectionProperties">
<value>bigStringTryClob=true;clientEncoding=UTF-8;defaultRowPrefetch=50;serverEncoding=ISO-8859-1</value>
</property>
</bean>
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
</bean>
<!-- myBatis -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:META-INF/mybatis/score-configuration.xml" />
<property name="mapperLocations" value="classpath*:META-INF/mybatis/mapper/*.xml" />
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="commonSqlSessionDao" abstract="true">
<property name="sqlSessionFactory">
<ref bean="sqlSessionFactory" />
</property>
</bean>
-----post the code that we how to use the template now
the jmsTemplate wrapped in a class
public class MessageProducer {
private JmsTemplate jmsTemplate;
private ActiveMQQueue scoreQueue;
public void sendScoreQueue(Map<String, String> userMap) {
sendMessage(this.scoreQueue, userMap);
}
private void sendMessage(Destination destination, final Map<String, String> map) {
this.jmsTemplate.send(destination, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
MapMessage message = session.createMapMessage();
for (String key : map.keySet()) {
message.setStringProperty(key, (String) map.get(key));
}
return message;
}
});
}
}
And we use a thead to send call the MessageProducer class's sendScoreQueue method.
As follows:
//the code is old and ugly.that is the original position we call the mq.
ThreadUtils.execute(new Thread(new SendMsgThread(dycc, ScoreMQSendType.SEND_TYPE_SCORE)));
///
public class ThreadUtils {
protected static ThreadPoolExecutor executor = null;
public static Properties Props = null;
public static void execute(Thread thread) {
executor.execute(thread);
}
static {
if (executor == null)
Integer corePoolSize = 5;
Integer maximumPoolSize = 10;
Integer keepAliveTime = 3000;
executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.MINUTES,
new LinkedBlockingQueue());
}
}
public class SendMsgThread implements Runnable {
private Log log = LogFactory.getLog(SendMsgThread.class);
private Map<String, String> map;
private String type;
private static MessageProducer producer = null;
public SendMsgThread(Map<String, String> map, String type){
this.type = type;
this.map = map;
}
public void run() {
try {
if(type.equals(ScoreMQSendType.SEND_TYPE_SCORE) || type.equals(ScoreMQSendType.SEND_TYPE_REGISTER)) {
producer.sendMessage(map);
}
} catch (Exception e) {
this.log.error("sendMsgThread sendScoreQueue error.", e);
}
}
static {
if (producer == null) producer =
(MessageProducer )SpringContextHolder.getBean(MessageProducer .class);
}
}
For this scenario you should use PooledConnectionFactory instead of cachingConnectionFactory.
More information can be found here.The difference between them can be found here
I had the same problem recurring with same error, and the solution was obtained as a result of trial and error, use jms call to concurrent consumers max to 101, instead of 100, and see if results repeat, adding more to the value results the code executed further on debugger, you will reach a value when code works , Also the solution appears to be using a connection pool factory.
Try this, hope it works, rest my implementation is same as yours in bean file
I've encorporated quartz scheduler in diffrent java file in my JSP Struts/Hibernate application. My execute method looks like below:
public void execute(JobExecutionContext jExeCtx) throws JobExecutionException {
try {
userDetailManager = new UserDetailManagerImpl();
userDetailManager.sendMailTxnDetailsEveryNight();
} catch (ApplicationException ex) {
java.util.logging.Logger.getLogger(JobClass.class.getName()).log(Level.SEVERE, null, ex);
}
}
Then im calling sendMailTxnDetailsEveryNight method and looks like:
public void sendMailTxnDetailsEveryNight() throws ApplicationException{
List<RemittanceTransactionBean> rBean = remittanceTransactionDao.getTodayTxnSummary();
return rBean;
}
Im getting nullpointerException at given point :
java.lang.NullPointerException
at com.mtmrs.business.user.impl.UserDetailManagerImpl.sendMailTxnDetailsEveryNight(UserDetailManagerImpl.java:754)
at com.mtmrs.util.common.JobClass.execute(JobClass.java:44)
How do i need to call the getTodayTxnSummary(); so that i dont get any error. I defined the remittanceTransactionDao in applicationContext as well:
<bean id="userDetailManager" parent="abstractTxDefinition">
<property name="target">
<bean class="com.mtmrs.business.user.impl.UserDetailManagerImpl">
<property name="remittanceTransactionDao" ref="remittanceTransactionDao"></property>
</bean>
</property>
</bean>
I tried debugging and see, the remittanceTransactionDao is null. I also tried setting below before calling method remittanceTransactionDao. This way the session variable im using in sendMailTxnDetailsEveryNight is null. I m stuck here.
remittanceTransactionDao = new RemittanceTransactionDaoHibernate(RemittanceTransaction.class);
I removed the classes and configured the follwing in my application-Context Dao.xml.
<bean name="runMeJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.mtmrs.util.common.RunMeJob" />
<property name="jobDataAsMap">
<map>
<entry key="userDetailManager" value-ref="userDetailManager" />
</map>
</property>
</bean>
<bean id="cronTrigger"
class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="runMeJob" />
<property name="cronExpression" value="0 0 10,12,14,16,18,20,22,23 * * ?" />
</bean>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobDetails">
<list>
<ref bean="runMeJob" />
</list>
</property>
<property name="triggers">
<list>
<ref bean="cronTrigger" />
</list>
</property>
</bean>
Then i removed everything about the quartz implementaion code whatever i was trying to make, and added this class:
package com.mtmrs.util.common;
import com.mtmrs.business.user.UserDetailManager;
import com.mtmrs.util.logger.MTMRSLogger;
import com.mtmrs.util.logger.ApplicationException;
import java.util.logging.Level;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
public class RunMeJob extends QuartzJobBean {
UserDetailManager userDetailManager;
public UserDetailManager getUserDetailManager() {
return userDetailManager;
}
public void setUserDetailManager(UserDetailManager userDetailManager) {
this.userDetailManager = userDetailManager;
}
#Override
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
System.out.print("Entering Class: Job Class , method: execute");
try {
userDetailManager.sendMailTxnDetailsEveryNight();
} catch (ApplicationException ex) {
java.util.logging.Logger.getLogger(RunMeJob.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.print("Exiting Class: Job Class , method: execute");
}
}
Also i downgraded the version of quartz jar to 1.x.
I needed to use a method in userDetailManager (ie sendMailTxnDetailsEveryNight) object as the job that run every 2 hours as specified in the trigger.
Basically i followed this link: Mykong
Hope this can be of help to someone.
I have a default database and sometimes I have to make a select in another database.
I've searched many blogs and questions here about this, but couldn't make it work.
Tried the http://blog.springsource.org/2007/01/23/dynamic-datasource-routing/ way. Nothing.
Code for RouterDataSource class:
public class RouterDataSource extends AbstractRoutingDataSource {
#Override
protected DataSourceEnum determineCurrentLookupKey() {
return DataSourceContextHolder.getTargetDataSource();
}
}
Code for DataSourceContextHolder class:
public class DataSourceContextHolder {
private static final ThreadLocal<DataSourceEnum> contextHolder = new ThreadLocal<DataSourceEnum>();
public static void setTargetDataSource(DataSourceEnum targetDataSource) {
Assert.notNull(targetDataSource, "Target data source cannot be null");
contextHolder.set(targetDataSource);
}
public static DataSourceEnum getTargetDataSource() {
if (contextHolder.get() != null)
return (DataSourceEnum) contextHolder.get();
else
return DataSourceEnum.DB1;
}
public static void resetDefaultDataSource() {
contextHolder.remove();
}
}
Code for the method calling to change the database:
#Override
public CodeHD getCategoryByCode(String code) throws BusinessException {
DataSourceContextHolder.setTargetDataSource(DataSourceEnum.DATABASE2);
return (CodeHD) persistency.getObject(GETOBJECT_BY_CODE, code);
}
Code for DatasourceEnum class:
public enum DataSourceEnum {
DB1,
DB2;
}
And finally the configuration on my applicationContext.xml:
<bean id="parentDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" abstract="true">
<property name="driverClass" value="oracle.jdbc.pool.OracleDataSource" />
<property name="acquireIncrement" value="10" />
<property name="idleConnectionTestPeriod" value="60" />
<property name="maxStatements" value="50" />
<property name="minPoolSize" value="5" />
<property name="maxPoolSize" value="15" />
</bean>
<bean id="database1DS" parent="parentDataSource">
<property name="jdbcUrl" value="jdbc:oracle:thin:#database1:1521:xe" />
<property name="user" value="user" />
<property name="password" value="password" />
</bean>
<bean id="database2DS" parent="parentDataSource">
<property name="jdbcUrl" value="jdbc:oracle:thin:#database2:1521:xe" />
<property name="user" value="user" />
<property name="password" value="password" />
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="dataSource" class="package.RouterDataSource">
<property name="defaultTargetDataSource" ref="database1DS"/>
<property name="targetDataSources">
<map key-type="package.DataSourceEnum">
<entry key="DB1" value-ref="database1DS"/>
<entry key="DB2" value-ref="database2DS"/>
</map>
</property>
</bean>
The problem is that when I set it to DB2 it won't change.
Can anyone help me?
Try to make both static method as non static and pass R reference if the context holder.
First make sure that database2DS is working correctly. Make the defaultTargetDatasource database2DS and verify that it is not using DB1 still and there are no other errors using database2DS as the default. If the AbstractRoutingDataSource fails to resolve a DataSource in the targetDataSources you cannot switch to it.
AbstractRoutingDataSource will only change the DataSource when getConnection is called. Whatever persistence framework you're using is probably caching the Connection and not calling getConnection in between persistency.getObject(). However you are getting your persistency object, try getting a new persistency object after you change the datasource in DataSourceContextHolder. If this solves your problem, try creating a class that maintains your persistency object and handles changing the datasource. That way when you change the datasource you can modify your persistency manager object in one spot.