Spring with quartz - spring

I have created quartz application using spring 3.1.
I have created one xml file Spring-Quartz.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="runMeTask" class="com.grit.quartz.RunMeTask" />
<!-- Spring Quartz -->
<bean name="runMeJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.grit.quartz.RunMeJob" />
<property name="jobDataAsMap">
<map>
<entry key="runMeTask" value-ref="runMeTask" />
</map>
</property>
</bean>
<!-- <bean id="runMeJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="runMeTask" /> <property name="targetMethod"
value="printMe" /> </bean> -->
<!-- Simple Trigger, run every 5 seconds -->
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail" ref="runMeJob" />
<property name="repeatInterval" value="5000" />
<property name="startDelay" value="1000" />
</bean>
<!-- Cron Trigger, run every 5 seconds -->
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="runMeJob" />
<property name="cronExpression" value="0/1 * * * * ?" />
</bean>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobDetails">
<list>
<ref bean="runMeJob" />
</list>
</property>
<property name="triggers">
<list>
<ref bean="simpleTrigger" />
</list>
</property>
<property name="quartzProperties">
<props>
<prop key="org.quartz.threadPool.threadCount">15</prop>
</props>
</property>
</bean>
When i am executing this file as standalone application using
new ClassPathXmlApplicationContext("Spring-Quartz.xml");
its working fine.
But i need to start this application when i am going to deploy this application in tomcat.
For this i created ServletContextListener and in context initalized i Call
new ClassPathXmlApplicationContext("Spring-Quartz.xml");
Its working fine but after i shutdown my tomcat, Schedular still working.So how can i shutdown the schedular or is there any other way to intialize a schedular ??

In the Destroy method , call the scheduler.shutdown() method.

Add to <props> the following:
<prop key="org.quartz.threadPool.makeThreadsDaemons">true</prop>
This should make quartz's threads to terminate upon application shutdown.

Quartz Job Scheduler is Open Source for Job Automation by scheduling Time Interval. So that the job can be executed when ever the Trigger is fired. Trigger Listeners fires at a specifid fire time.
QuartzInitializerListener with Spring
When ever records get changed in DBS trigger to find and send sms
Dto class Which Holds DB data
public class EmpDto {
private Integer id;
private String name;
private Integer age;
private Integer salary;
private String address;
private List<EmpDto> empList;.....
To Scedule a job/task to run at specific date & time.
component/class has to implement JOB interface and #override execute(). so that the ececute()
method code will be executed by scheduler when trigger is raised.
public class Quartz_JOB implements Job{
private EmpDao edao; // configure in applicationContex.xml
public EmpDao getEdao() { return edao; }
public void setEdao(EmpDao edao) { this.edao = edao; }
public static Integer size;
public void execute(JobExecutionContext context) throws JobExecutionException {
Date time = context.getFireTime();
Date next_trigger_time =context.getNextFireTime();
System.out.println("### Current Trigget Time : "+time+"### Next Trigger Time : "+next_trigger_time);
JobKey job_key = context.getJobDetail().getKey();
JobDataMap dataMap = context.getMergedJobDataMap(); // Get all the keys from Listener.
System.out.println("Instance " + job_key + " of DumbJob says: " + jobSays + ", and val is: " + record_Size);
System.out.println("Trigger Data : "+curr_Record_Size);
System.out.println("#######Empdao : "+edao);
}
String jobSays;
int record_Size;
int curr_Record_Size;
public int getCurr_Record_Size() { return curr_Record_Size; }
public void setCurr_Record_Size(int curr_Record_Size) {
this.curr_Record_Size = curr_Record_Size;
}
}
web.xml
<listener>
<listener-class>org.quartz.ee.servlet.QuartzInitializerListener</listener-class>
</listener>
WebListener
#WebListener
public class QuartzListener extends QuartzInitializerListener {
Scheduler scheduler = null;
Integer size = null;
#Override
public void contextInitialized(ServletContextEvent servletContext) {
System.out.println("Context Initialized");
try {
// JobDetails used to create instances of a class which Implement <<job>>
// <<JobBuilder>> used to define/build instances of <<JobDetails>>. Which define istances of job.
JobDetail job1 = JobBuilder
.newJob(Quartz_JOB.class)
.withIdentity("Job_ID", "Group1")
.usingJobData("jobSays", "Hello World!")
.usingJobData("recird_Size", 3)
.build();
// <<Trigger>> a component that defines the scheduled 'Time Interval'. So that the given job to execute.
// << TriggerBuilder>> used to create Trigger Instance.
Trigger trigger = TriggerBuilder
.newTrigger()
.withIdentity("Trigger_ID", "Group1")
.forJob("Job_ID", "Group1")
.withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))
.usingJobData("curr_Record_Size", edto.getEmpList().size())
.build();
// Setup the Job and Trigger with Scheduler & schedule jobs
scheduler = new StdSchedulerFactory().getScheduler();
scheduler.start();
scheduler.scheduleJob(job1, trigger);
}catch (SchedulerException e) {
e.printStackTrace();
}
}
#Override
public void contextDestroyed(ServletContextEvent servletContext) {
System.out.println("Context Destroyed");
try {
scheduler.shutdown();
System.out.println("Quartz stoped");
}catch (SchedulerException e) {
e.printStackTrace();
}
}
}
When ever trigger is raised, execute() method will invoke in that static variable hold record size. get current size if it differs then send an email (Write email logic in another class & call that method from execute() by passing size).
To Generate Corn Expression

Related

Java Mail dont work when executed from bean

Here is my #Service class whose remind() method is called from the front-end.
#Service
public class EmailManagerImpl implements EmailManager {
private MailSender mailSender;
private SimpleMailMessage templateMessage;
public void setMailSender(MailSender mailSender) {
this.mailSender = mailSender;
}
public void setTemplateMessage(SimpleMailMessage templateMessage) {
this.templateMessage = templateMessage;
}
#Override
public void remind(Appointment appointment) {
Person patient = appointment.getPatient();
SimpleMailMessage msg = new SimpleMailMessage(this.templateMessage);
msg.setTo(patient.getMail());
msg.setText("Szanowny pacjencie " + patient.getFirstName() + " "
+ patient.getSurname() + " "
+ appointment.toString());
try {
mailSender.send(msg);
} catch (MailException ex) {
// log it and go on
System.err.println(ex.getMessage());
}
}
I am sure that templeMessage and mailSender are injected correctly. After whole process is executed i dont get any error, no exception no debugging info from true. When i try to run one of many demos, it works just fine. The only diffrence is that my application is on Tomcat + i invoke method from bean. Any ideas?
I can follow debug up to the following method from SimpleMailMessage line, later i get message that source is not found:
//---------------------------------------------------------------------
// Implementation of MailSender
//---------------------------------------------------------------------
public void send(SimpleMailMessage simpleMessage) throws MailException {
send(new SimpleMailMessage[] { simpleMessage });
}
My applicationConfig:
<!-- Wysylanie maili -->
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="${mail.host}" />
<property name="port" value="${mail.port}" />
<property name="username" value="${mail.username}" />
<property name="password" value="${mail.password}" />
<property name="protocol" value="smtp" />
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.ssl.trust">smtp.gmail.com</prop>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.starttls.enable">true</prop>
<prop key="mail.smtps.debug">true</prop>
</props>
</property>
</bean>
<!-- this is a template message that we can pre-load with default state -->
<bean id="templateMessage" class="org.springframework.mail.SimpleMailMessage">
<property name="from" value="${mail.username}" />
<property name="subject" value="${mail.subject}" />
</bean>
<bean id="emailManagerImpl" class="com.przychodnia.rejestracja.integration.EmailManagerImpl">
<property name="mailSender"><ref bean="mailSender"/></property>
<property name="templateMessage"><ref bean="templateMessage"/></property>
</bean>

spring batch ItemReader FlatFileItemReader set cursor to start reading from a particular line or set linestoskip dynamically

In my springbatch+quartz setup, I am reading a CSV File using FlatFileItemReader. I want to set the cursor for the reader to start the next jobinstance with the given parameters for reader. Is it possible?
<bean id="cvsFileItemReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
<!-- Read a csv file -->
<property name="resource" value="classpath:cvs/input/report.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="id,impressions" />
</bean>
</property>
<property name="fieldSetMapper">
<bean
class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
<property name="prototypeBeanName" value="report" />
</bean>
</property>
</bean>
</property>
</bean>
The idea is to continue reading the file where last failure occured in the next execution. I am putting an integer 'writecursor' for each line written in my customWriter.
public void write(List<? extends Report> items) throws Exception {
System.out.println("writer..." + items.size() + " > ");
for(Report item : items){
System.out.println("writing item id: " + item.getId());
System.out.println(item);
}
//getting stepExecution by implementing StepExecutionListener
this.stepExecution.getExecutionContext().putInt("writecursor", ++writecursor);
}
Now, in the customItemReadListener, I want to get the update writecursor value and then skip the lines from the top to start reading from writecursor
public class CustomItemReaderListener implements ItemReadListener<Report>, StepExecutionListener {
ApplicationContext context = ApplicationContextUtils.getApplicationContext();
private StepExecution stepExecution;
#Override
public void beforeRead() {
//Skip lines somehow
}
Another thing I saw as a possible solution is to set linestoskip dynamically in itemreader. There is a thread here http://thisisurl.com/dynamic-value-for-linestoskip-in-itemreader but not answered yet. And here,
http://forum.spring.io/forum/spring-projects/batch/100950-accessing-job-execution-context-from-itemwriter
Use FlatFileItemReader.linesToSkip property setted injecting job Parameter value.
<bean id="myReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
<property name="linesToSkip" value="file:#{jobParameters['cursor']}" />
</bean>
A more easy way for implementing the lines to skip is by the following:
create a reader flat file reader in the xml, autowire the reader to the beforeStep of step execution listener as shown below
public class CustomStepListener implements StepExecutionListener {
#Autowired
#Qualifier("cvsFileItemReader")
FlatFileItemReader cvsFileItmRdr;
#Override
public void beforeStep(StepExecution stepExecution) {
System.out.println("StepExecutionListener -------- beforeStep");
cvsFileItmRdr.setLinesToSkip(4);
}
#Override
public ExitStatus afterStep(StepExecution stepExecution) {
System.out.println("StepExecutionListener - afterStep");
return null;
}
}
it is working fine for me.....

replace one class in bean property list in spring

I am working in broadleaf which is based on spring-mvc.
there are 3-4 blCustomPersistenceHandlers bean definition in different xml file based on project module.
<bean id="blCustomPersistenceHandlers" class="org.springframework.beans.factory.config.ListFactoryBean" scope="prototype">
<property name="sourceList">
<list>
<bean class="org.broadleafcommerce.admin.server.service.handler.CategoryCustomPersistenceHandler"/>
<bean class="org.broadleafcommerce.admin.server.service.handler.CustomerPasswordCustomPersistenceHandler"/>
<bean class="org.broadleafcommerce.openadmin.server.security.handler.AdminUserCustomPersistenceHandler"/>
<bean class="org.broadleafcommerce.admin.server.service.handler.CustomerCustomPersistenceHandler"/>
<bean class="org.broadleafcommerce.admin.server.service.handler.ProductCustomPersistenceHandler"/>
<bean class="org.broadleafcommerce.admin.server.service.handler.ChildCategoriesCustomPersistenceHandler"/>
<bean class="org.broadleafcommerce.admin.server.service.handler.SkuCustomPersistenceHandler"/>
</list>
</property>
</bean>
below in different xml files
<bean id="blCustomPersistenceHandlers" class="org.springframework.beans.factory.config.ListFactoryBean" scope="prototype">
<property name="sourceList">
<list>
<bean class="org.broadleafcommerce.cms.admin.server.handler.PageTemplateCustomPersistenceHandler"/>
<bean class="org.broadleafcommerce.cms.admin.server.handler.StructuredContentTypeCustomPersistenceHandler"/>
<bean class="org.broadleafcommerce.cms.admin.server.handler.SandBoxItemCustomPersistenceHandler"/>
<bean class="org.broadleafcommerce.cms.admin.server.handler.PendingSandBoxItemCustomPersistenceHandler"/>
<bean class="org.broadleafcommerce.cms.admin.server.handler.TimeDTOCustomPersistenceHandler"/>
<bean class="org.broadleafcommerce.cms.admin.server.handler.RequestDTOCustomPersistenceHandler"/>
<bean class="org.broadleafcommerce.cms.admin.server.handler.StructuredContentItemCriteriaCustomPersistenceHandler"/>
<bean class="org.broadleafcommerce.cms.admin.server.handler.PageItemCriteriaCustomPersistenceHandler"/>
</list>
</property>
</bean>
Above definitions reside into jar files that we included.
Now i want to replace one of this handler , for example ProductCustomPersistenceHandler,
I need to change some functionality regarding that handler, so I changed that handler as below in my xml file.
<bean id="org.broadleafcommerce.admin.server.service.handler.ProductCustomPersistenceHandler"
class="com.mycompany.server.service.handler.HCProductCustomPersistenceHandler" />
and also put bean defination into xml files
<bean id="blCustomPersistenceHandlers" class="org.springframework.beans.factory.config.ListFactoryBean"> <!-- scope="prototype" -->
<property name="sourceList">
<list>
<bean class="com.mycompany.server.service.handler.HCProductCustomPersistenceHandler"/>
</list>
</property>
</bean>
ProductCustomPersistenceHandler class
public class ProductCustomPersistenceHandler extends CustomPersistenceHandlerAdapter {
#Resource(name = "blCatalogService")
protected CatalogService catalogService;
private static final Log LOG = LogFactory.getLog(ProductCustomPersistenceHandler.class);
#Override
public Boolean canHandleAdd(PersistencePackage persistencePackage) {
String ceilingEntityFullyQualifiedClassname = persistencePackage.getCeilingEntityFullyQualifiedClassname();
String[] customCriteria = persistencePackage.getCustomCriteria();
return !ArrayUtils.isEmpty(customCriteria) && "productDirectEdit".equals(customCriteria[0]) && Product.class.getName().equals(ceilingEntityFullyQualifiedClassname);
}
#Override
public Boolean canHandleUpdate(PersistencePackage persistencePackage) {
return canHandleAdd(persistencePackage);
}
#Override
public Entity add(PersistencePackage persistencePackage, DynamicEntityDao dynamicEntityDao, RecordHelper helper) throws ServiceException {
Entity entity = persistencePackage.getEntity();
try {
PersistencePerspective persistencePerspective = persistencePackage.getPersistencePerspective();
Product adminInstance = (Product) Class.forName(entity.getType()[0]).newInstance();
Map<String, FieldMetadata> adminProperties = helper.getSimpleMergedProperties(Product.class.getName(), persistencePerspective);
adminInstance = (Product) helper.createPopulatedInstance(adminInstance, entity, adminProperties, false);
adminInstance = (Product) dynamicEntityDao.merge(adminInstance);
CategoryProductXref categoryXref = new CategoryProductXrefImpl();
categoryXref.setCategory(adminInstance.getDefaultCategory());
categoryXref.setProduct(adminInstance);
if (adminInstance.getDefaultCategory() != null && !adminInstance.getAllParentCategoryXrefs().contains(categoryXref)) {
categoryXref = (CategoryProductXref) dynamicEntityDao.merge(categoryXref);
adminInstance.getAllParentCategoryXrefs().add(categoryXref);
}
//Since none of the Sku fields are required, it's possible that the user did not fill out
//any Sku fields, and thus a Sku would not be created. Product still needs a default Sku so instantiate one
if (adminInstance.getDefaultSku() == null) {
Sku newSku = catalogService.createSku();
adminInstance.setDefaultSku(newSku);
adminInstance = (Product) dynamicEntityDao.merge(adminInstance);
}
//also set the default product for the Sku
adminInstance.getDefaultSku().setDefaultProduct(adminInstance);
dynamicEntityDao.merge(adminInstance.getDefaultSku());
return helper.getRecord(adminProperties, adminInstance, null, null);
} catch (Exception e) {
LOG.error("Unable to add entity for " + entity.getType()[0], e);
throw new ServiceException("Unable to add entity for " + entity.getType()[0], e);
}
}
#Override
public Entity update(PersistencePackage persistencePackage, DynamicEntityDao dynamicEntityDao, RecordHelper helper) throws ServiceException {
Entity entity = persistencePackage.getEntity();
try {
PersistencePerspective persistencePerspective = persistencePackage.getPersistencePerspective();
Map<String, FieldMetadata> adminProperties = helper.getSimpleMergedProperties(Product.class.getName(), persistencePerspective);
Object primaryKey = helper.getPrimaryKey(entity, adminProperties);
Product adminInstance = (Product) dynamicEntityDao.retrieve(Class.forName(entity.getType()[0]), primaryKey);
adminInstance = (Product) helper.createPopulatedInstance(adminInstance, entity, adminProperties, false);
adminInstance = (Product) dynamicEntityDao.merge(adminInstance);
CategoryProductXref categoryXref = new CategoryProductXrefImpl();
categoryXref.setCategory(adminInstance.getDefaultCategory());
categoryXref.setProduct(adminInstance);
if (adminInstance.getDefaultCategory() != null && !adminInstance.getAllParentCategoryXrefs().contains(categoryXref)) {
adminInstance.getAllParentCategoryXrefs().add(categoryXref);
}
return helper.getRecord(adminProperties, adminInstance, null, null);
} catch (Exception e) {
LOG.error("Unable to update entity for " + entity.getType()[0], e);
throw new ServiceException("Unable to update entity for " + entity.getType()[0], e);
}
}
}
I just extend this handler and make my new handler , as it runs only core handler is executing, I want to execute my handler.
But this is not working.
I can't change into core part, so I just need to replace handler with my handler.
How can I do that?
Is that possible in spring?
For custom persistence handlers specifically, you can remove the core handlers by using the blCustomPersistenceHandlerFilters bean. So in your case you would define your beans like this:
<bean id="blCustomPersistenceHandlerFilters" class="org.springframework.beans.factory.config.ListFactoryBean" scope="prototype">
<property name="sourceList">
<list>
<bean class="org.broadleafcommerce.openadmin.server.service.handler.DefaultCustomPersistenceHandlerFilter">
<property name="filterCustomPersistenceHandlerClassnames">
<list>
<value>org.broadleafcommerce.admin.server.service.handler.ProductCustomPersistenceHandler</value>
</list>
</property>
</bean>
</list>
</property>
</bean>
Then you can add your own CPH to the list like you were doing before:
<bean id="blCustomPersistenceHandlers" class="org.springframework.beans.factory.config.ListFactoryBean"> <!-- scope="prototype" -->
<property name="sourceList">
<list>
<bean class="com.mycompany.server.service.handler.HCProductCustomPersistenceHandler"/>
</list>
</property>
</bean>
And now the BLC Product custom persistence handler will not run but yours will.
This is probably a little too complex for your simple purposes of wanting to replace the out-of-the-box one with your custom one. It's possible that there is a good reason why we did it like this, but I added a GitHub Issue for it to investigate further.

spring mybatis transaction getting committed

I am trying to use mybatis spring transaction management
My problem is that the transactions are getting committed even if an exception is thrown.
Relatively new to this, anykind of help is much appreciated.
Following are the code snippets
spring xml configuration
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:Config.properties</value>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${db.driver}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.user}"/>
<property name="password" value="${db.pass}"/>
<property name="defaultAutoCommit" value="false" />
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:Configuration.xml" />
<property name="dataSource" ref="dataSource" />
</bean>
<bean class="org.mybatis.spring.SqlSessionTemplate" id="sqlSessionTemplate">
<constructor-arg ref="sqlSessionFactory"/>
</bean>
Service class
#Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRED)
public void insertNotes(String noteTypeId,String confidentialValue,String summaryValue,String notes ,String notesId,String noteTypeValue,
String claimNumber,String notepadId,String mode)
{
NotepadExample notepadExample= new NotepadExample();
//to be moved into dao class marked with transaction boundaries
Notepad notepad = new Notepad();
notepad.setAddDate(new Date());
notepad.setAddUser("DummyUser");
if("true".equalsIgnoreCase(confidentialValue))
confidentialValue="Y";
else
confidentialValue="N";
notepad.setConfidentiality(confidentialValue);
Long coverageId=getCoverageId(claimNumber);
notepad.setCoverageId(coverageId);
notepad.setDescription(summaryValue);
notepad.setEditUser("DmyEditUsr");
//notepad.setNotepadId(new Long(4)); //auto sequencing
System.out.println(notes);
notepad.setNotes(notes);
notepad.setNoteType(noteTypeValue); //Do we really need this?
notepad.setNoteTypeId(Long.parseLong(notesId));
if("update".equalsIgnoreCase(mode))
{
notepad.setNotepadId(new Long(notepadId));
notepad.setEditDate(new Date());
notepadMapper.updateByPrimaryKeyWithBLOBs(notepad);
}
else
notepadMapper.insertSelective(notepad);
throw new java.lang.UnsupportedOperationException();
}
Not sure where I am going wrong...
The current call is from the controller as given below
#Controller
public class NotesController {
private static final Logger logger = LoggerFactory
.getLogger(NotesController.class);
#Autowired
private Utils utility;
#Autowired
NotepadService notepadService;
public #ResponseBody List<? extends Object> insertNotes(HttpServletRequest request,
HttpServletResponse response,#RequestParam("noteTypeValue") String noteTypeId,
#RequestParam("confidentialValue")String confidentialValue,
#RequestParam("summaryValue")String summaryValue,
#RequestParam("notes")String notes ,
#RequestParam("notesId")String notesId,
#RequestParam("noteTypeValue")String noteTypeValue,
#RequestParam("claimNumber")String claimNumber,
#RequestParam("notepadId")String notepadId,
#RequestParam("mode")String mode) {
try {
notepadService.insertNotes(noteTypeId, confidentialValue, summaryValue, notes, notesId, noteTypeValue, claimNumber, notepadId, mode);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
I had the same issue. I am also relatively new to spring. But according to me it depends on how you are calling your insertNotes() method. If you are calling it from another local method then it will not work, because spring has no way of know that it is called and to start the transaction.
If you are calling it from a method of another class by using autowired object of the class which contains insertNotes() method, then it should work.
For example
class ABC
{
#Autowired
NotesClass notes;
public void testMethod() {
notes.insertNotes();
}
}
class NotesClass
{
#Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRED)
public void insertNotes(String noteTypeId,
String confidentialValue,
String summaryValue,String notes ,
String notesId,String noteTypeValue,
String claimNumber,
String notepadId,
String mode) {
//Your code
}
}
You can try using transaction template. Remove #Tranasactional annotation from method and following code to xml file.
<bean id="trTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="timeout" value="30"/>
<property name="transactionManager" ref="transactionManager"/>
</bean>
Create object of Trasactiontemplate and call insertNotes from controller like this
#Autowired
private TransactionTemplate transactionTemplate;
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
#Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
try {
insertNotes();
} catch (Exception e) {
transactionStatus.setRollbackOnly();
logger.error("Exception ocurred when calling insertNotes", e);
throw new RuntimeException(e);
}
}
});
Note : You have to make all parameters final before calling insertNotes method

How to use #Autowired in a Quartz Job?

i am using quartz with spring
and i want to inject/use another class in the job class
and i don't know how to do it correctly
the xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!-- Scheduler task -->
<bean name="schedulerTask" class="com.mkyong.quartz.SchedulerTask" />
<!-- Scheduler job -->
<bean name="schedulerJob"
class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.mkyong.quartz.SchedulerJob" />
<property name="jobDataAsMap">
<map>
<entry key="schedulerTask" value-ref="schedulerTask" />
</map>
</property>
</bean>
<!-- Cron Trigger -->
<bean id="cronTrigger"
class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="schedulerJob" />
<property name="cronExpression" value="0/10 * * * * ?" />
</bean>
<!-- Scheduler -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobDetails">
<list>
<ref bean="schedulerJob" />
</list>
</property>
<property name="triggers">
<list>
<ref bean="cronTrigger" />
</list>
</property>
</bean>
</beans>
the quartz job:
package com.mkyong.quartz;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
public class SchedulerJob extends QuartzJobBean
{
private SchedulerTask schedulerTask;
public void setSchedulerTask(SchedulerTask schedulerTask) {
this.schedulerTask = schedulerTask;
}
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
schedulerTask.printSchedulerMessage();
}
}
the task to be executed:
package com.mkyong.quartz;
public class SchedulerTask {
public void printSchedulerMessage() {
System.out.println("Struts 2 + Spring + Quartz ......");
}
}
i want to inject another DTO class that deals with Database in the task class
to do some database work in the task, how to do that ?
In your solution you are using the spring #Autowired annotation in a class that is not instantiated by Spring. Your solution will still work if you remove the #Autowired annotation because Quartz is setting the property, not Spring.
Quartz will try to set every key within the JobDataMap as a property. E.g. since you have a key "myDao" Quartz will look for a method called "setMyDao" and pass the key's value into that method.
If you want Spring to inject spring beans into your jobs, create a SpringBeanJobFactory and set this into your SchedulerFactoryBean with the jobFactory property within your spring context.
SpringBeanJobFactory javadoc:
Applies scheduler context, job data map and trigger data map entries
as bean property values
Not sure if this is what you want, but you can pass some configuration values to the Quartz job. I believe in your case you could take advantage of the jobDataAsMap property you already set up, e.g.:
<property name="jobDataAsMap">
<map>
<entry key="schedulerTask" value-ref="schedulerTask" />
<entry key="param1" value="com.custom.package.ClassName"/>
</map>
</property>
Then you should be able to access it in your actual Java code in manual way:
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
schedulerTask.printSchedulerMessage();
System.out.println(context.getJobDetail().getJobDataMap().getString("param1"));
}
Or using the magic Spring approach - have the param1 property defined with getter/setter. You could try defining it with java.lang.Class type then and have the done automatically (Spring would do it for you):
private Class<?> param1;
// getter & setter
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
schedulerTask.printSchedulerMessage();
System.out.println("Class injected" + getParam1().getName());
}
I haven't tested it though.
ApplicationContext springContext =
WebApplicationContextUtils.getWebApplicationContext(
ContextLoaderListener.getCurrentWebApplicationContext().getServletContext()
);
Bean bean = (Bean) springContext.getBean("beanName");
bean.method();
As mentioned in inject bean reference into a Quartz job in Spring? you can use spring SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
#Named
public class SampleJob implements Job {
#Inject
private AService aService;
#Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
//Do injection with spring
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
aService.doIt();
}
}
As mentioned it may not wotk on some spring version but I have tested it on 4.2.1.RELEASE which worked fine.
this is my solution:
public class MySpringBeanJobFactory extends
org.springframework.scheduling.quartz.SpringBeanJobFactory implements
ApplicationContextAware {
private ApplicationContext ctx;
#Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.ctx = applicationContext;
}
#Override
protected Object createJobInstance(TriggerFiredBundle bundle)
throws Exception {
Object jobInstance = super.createJobInstance(bundle);
ctx.getAutowireCapableBeanFactory().autowireBean(jobInstance);
return jobInstance;
}
}
then config the class of MySpringBeanJobFactory in the xml:
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobFactory">
<bean class="com.xxxx.MySpringBeanJobFactory" />
</property>
<property name="configLocation" value="classpath:quartz.properties" />
<property name="triggers">
<list>
<ref bean="cronTrigger"/>
</list>
</property>
</bean>
Good luck ! :)

Resources