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.
Related
I'm getting four 'no setter found for property 'xxxx' in class com.rusapp.batch.trans.OLFMWriter'. A fifth bean in that class does not have an error, inputQueue. The rest have errors in the xml below at each of the property lines.
The beans appear as such:
<bean id="inputQueue" class="com.rusapp.batch.trans.OLFMWriter">
<property name="inputQueue" value="${${ENV}_MQ_FM_INPUT_QUEUE}" />
</bean>
<bean id="replyQueue" class="com.rusapp.batch.trans.OLFMWriter">
<property name="replyQueue" value="${${ENV}_MQ_FM_REPLY_QUEUE}" />
</bean>
<bean id="mqConnectionFactory" class="com.rusapp.batch.trans.OLFMWriter">
<property name="mqConnectionFactory" ref="mqConnection" />
</bean>
<bean id="JMSDestination"
class="com.rusapp.batch.trans.OLFMWriter">
<property name="JMSDestination" ref="jmsDestinationResolver" />
</bean>
<bean id="JMSReplyTo"
class="com.rusapp.batch.trans.OLFMWriter">
<property name="JMSReplyTo" ref="jmsDestinationResolverReceiver" />
</bean>
The setters in the class appear as follows:
public static void setMqConnectionFactory(MQConnectionFactory _mqConnectionFactory) {
OLFMWriter._mqConnectionFactory = _mqConnectionFactory;
}
public static void setReplyQueue(String _replyQueue) {
OLFMWriter._replyQueue = _replyQueue;
}
public static void setJMSDestination(Destination _JMSDestination) {
OLFMWriter._JMSDestination = _JMSDestination;
}
public static void setJMSReplyTo(Destination _JMSReplyTo) {
OLFMWriter._JMSReplyTo = _JMSReplyTo;
}
public void setInputQueue(String inputQueue){
_inputQueue = inputQueue;
}
This is not my code and I'm not too knowledgeable with Spring yet but I can't find anything wrong with the setter names. I thought it was a workspace error but they have persisted through several restarts of Eclipse.
Can anyone find any obvious faults with this code?
Your setters are static which means that they don't conform to the java beans specification.
I think you'll want to use a MethodInvokingFactorybean instead.
<bean abstract="true" id="abstractParent" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="com.rusapp.batch.trans.OLFMWriter"/>
</bean>
<bean id="inputQueue" parent="abstractParent">
<property name="staticMethod" value="setInputQueue" />
<property name="arguments">
<list><value>${${ENV}_MQ_FM_INPUT_QUEUE}</value></list>
</property>
</bean>
<bean id="replyQueue" parent="abstractParent">
<property name="staticMethod" value="setReplyQueue" />
<property name="arguments">
<list><value>${${ENV}_MQ_FM_REPLY_QUEUE}</value></list>
</property>
</bean>
etc...
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
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.
All. Attached herewith all the files. If I give the same name for both bean property name and reference, it returns the object. But it returns null, in case both are different. Please help. Thank you so much.
The AuthenticateAction.java file has got the detailed comments inside it.....
below are my files list:
WIRAdminBaseAction.java ---> my base action
AuthenticateAction.java ---> my java file that calls the bean here
applicationContext_MNC.xml
The below way of calling works...... This is not encouraged, as we
should not use applicationContext always
ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(getServletRequest().getSession().getServletConte xt());
ICacheDelegate cacheAction = (ICacheDelegate)applicationContext.getBean("BMOCacheDelegate");
The below way of calling does NOT work .... returns null value....
Please help... I assume that, since I have extended the
WIRAdminBaseAction, i should be able to call the getCacheDelegate
directly and it should return my cacheDelegate object ... Again,
Please note.....if I change my applicationContext_MNC.xml as below,
the below way of calling works fine. But, i don't want to change my
applicationContext_MNC.xml as below, due to some necessity.
<bean id="BMOWIRAdminBaseAction" class="com.symcor.wiradmin.web.action.WIRAdminBase Action">
<property name="cacheDelegate">
<ref bean="cacheDelegate" />
</property>
</bean>
<bean id="cacheDelegate" class="com.symcor.wiradmin.delegate.CacheDelegate" >
<property name="statusDBDAO"><ref bean="BMOStatusDBDAO" /></property>
</bean>
Is it that the name and bean should have the same value.... ??? No
Need to be.....Am i right ? Please advise.
getCacheDelegate().getActorAction(1); // this way of calling doesn't work and returns null value. please help.
MY CODE Follows below.
AuthenticateAction.java
package com.symcor.wiradmin.web.action;
import java.net.UnknownHostException;
import java.sql.SQLException;
import org.bouncycastle.crypto.CryptoException;
import org.springframework.context.ApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.web.context.support.WebApplica tionContextUtils;
import com.symcor.wiradmin.delegate.ICacheDelegate;
public class AuthenticateAction extends WIRAdminBaseAction {
private static final long serialVersionUID = 1L;
public String authenticate() throws UnknownHostException, CryptoException,
DataAccessException, SQLException{
/** This way of calling works...... This is not encouraged, as we should not use applicationContext always **/
ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContex t(getServletRequest().getSession().getServletConte xt());
ICacheDelegate cacheAction = (ICacheDelegate) applicationContext.getBean("BMOCacheDelegate");
/** The below way of calling does NOT work .... returns null value.... Please help...
* I assume that, since I have extended the WIRAdminBaseAction, i should be able to call the getCacheDelegate directly
* and it should return my cacheDelegate object ...
* Again, Please note.....if I change my applicationContext_MNC.xml as below, the below way of calling works fine...
* but, i don't want to change my applicationContext_MNC.xml as below, due to some necessity.
<bean id="BMOWIRAdminBaseAction" class="com.symcor.wiradmin.web.action.WIRAdminBase Action">
<property name="cacheDelegate">
<ref bean="cacheDelegate" />
</property>
</bean>
<bean id="cacheDelegate" class="com.symcor.wiradmin.delegate.CacheDelegate" >
<property name="statusDBDAO"><ref bean="BMOStatusDBDAO" /></property>
</bean>
... is it that the name and bean should have the same value.... ??? No Need to be.....Am i right ? Please advise.
*
* **/
getCacheDelegate().getActorAction(1); // this way of calling doesn't work and returns null value. please help.
return "success";
}
}
WIRAdminBaseAction.java
package com.symcor.wiradmin.web.action;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.interceptor.ParameterAware;
import org.apache.struts2.interceptor.SessionAware;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.Preparable;
import com.opensymphony.xwork2.config.entities.Parameteri zable;
import com.symcor.wiradmin.delegate.ICacheDelegate;
public class WIRAdminBaseAction extends ActionSupport implements Preparable, ParameterAware, Parameterizable, SessionAware,RequestAware {
private HttpServletRequest request;
private static final long serialVersionUID = 1L;
private HttpServletResponse response;
private ICacheDelegate cacheDelegate;
private Map session;
private Map<String, String> params;
private Map parameters;
public void prepare() throws Exception {
}
public String execute() throws Exception {
return SUCCESS;
}
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
public HttpServletRequest getServletRequest() {
return this.request;
}
public void setServletResponse(HttpServletResponse response) {
this.response = response;
}
public HttpServletResponse getServletResponse() {
return this.response;
}
public ICacheDelegate getCacheDelegate() {
return cacheDelegate;
}
public void setCacheDelegate(ICacheDelegate cacheDelegate) {
this.cacheDelegate = cacheDelegate;
}
public void addParam(final String key, final String value) {
this.params.put(key, value);
}
public Map getParams() {
return params;
}
public void setParams(final Map<String, String> params) {
this.params = params;
}
public Map getSession() {
return this.session;
}
public void setSession(final Map session) {
this.session = session;
}
public void setParameters(final Map param) {
this.parameters = param;
}
}
applicationContext_MNC.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- database configuration from property file -->
<bean id="BMOAdminDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close" lazy-init="default" autowire="default" dependency-check="default">
<property name="driverClass" value="${jdbc.driver}" ></property>
<property name="jdbcUrl" value="${admin.jdbc.url}" ></property>
<property name="user" value="${admin.jdbc.user}" ></property>
<property name="password" value="${admin.jdbc.password}" ></property>
<property name="initialPoolSize" value="3" ></property>
<property name="minPoolSize" value="3" ></property>
<property name="maxPoolSize" value="25" ></property>
<property name="acquireIncrement" value="1" ></property>
<property name="acquireRetryDelay" value="1000" ></property>
<property name="debugUnreturnedConnectionStackTraces" value="true" ></property>
<property name="maxIdleTime" value="300" ></property>
<property name="unreturnedConnectionTimeout" value="300000" ></property>
<property name="preferredTestQuery" value="SELECT COUNT(*) FROM LOCALE_CODE" ></property>
<property name="checkoutTimeout" value="300000" ></property>
<property name="idleConnectionTestPeriod" value="600000" ></property>
</bean>
<bean id="BMOWIRAdminBaseAction" class="com.symcor.wiradmin.web.action.WIRAdminBase Action">
<property name="cacheDelegate">
<ref bean="BMOCacheDelegate" />
</property>
</bean>
<bean id="BMOCacheDelegate" class="com.symcor.wiradmin.delegate.CacheDelegate" >
<property name="statusDBDAO"><ref bean="BMOStatusDBDAO" /></property>
</bean>
<bean id="BMOStatusDBDAO" class="com.symcor.wiradmin.dao.StatusDBDAO">
<property name="dataSource">
<ref bean="BMOAdminDataSource" />
</property>
</bean>
<!-- this bean is set to map the constants which needs to be configured as per
the environment to the java constants file -->
<bean id="envConstantsConfigbean" class="com.symcor.wiradmin.util.constants.Environm entConstantsSetter">
<property name="loginUrl" value="${login.url}"/>
<property name="logoutIR" value="${logout.from.image.retrieval}"/>
<property name="adminModuleUrl" value="${admin.url}"/>
<property name="adminUrlSym" value="${admin.url.sym}"/>
<property name="envProperty" value="${env.property}"/>
</bean>
</beans>
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.