package org.quartz;
import org.quartz.Scheduler;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Trigger;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.SchedulerException;
import org.quartz.impl.StdSchedulerFactory;
import static org.quartz.JobBuilder.*;
import static org.quartz.TriggerBuilder.*;
import static org.quartz.SimpleScheduleBuilder.*;
import static org.quartz.CronScheduleBuilder.*;
import static org.quartz.CalendarIntervalScheduleBuilder.*;
import static org.quartz.DateBuilder.*;
class myJob implements Job {
public void execute(JobExecutionContext context)
throws JobExecutionException
{
System.out.println("Hello! HelloJob is executing.");
}
}
public class schedule{
public static void main(String args[]) throws Exception{
System.out.println("Java working");
try {
// Grab the Scheduler instance from the Factory
JobKey jobKeyA = new JobKey("myJob", "group1");
JobDetail jobA = JobBuilder.newJob(myJob.class)
.withIdentity(jobKeyA).build();
// Trigger the job to run now, and then every 40 seconds
Trigger trigger1 = TriggerBuilder
.newTrigger()
.withIdentity("dummyTriggerName1", "group1")
.withSchedule(
CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))
.build();
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
// and start it off
scheduler.start();
// Tell quartz to schedule the job using our trigger
scheduler.scheduleJob(jobA, trigger1);
} catch (SchedulerException se) {
se.printStackTrace();
}
}
}
And I am getting an error of instantiating job and then obviously All triggers of Job set to ERROR state.
What is the reason?
and please help it is very important.
provide me the answer.
Error
[ERROR] 28 Dec 03:03:30.008 PM
DefaultQuartzScheduler_QuartzSchedulerThread
[org.quartz.core.ErrorLogger]
An error occured instantiating job to be executed. job= 'group1.myJob'
org.quartz.SchedulerException: Problem instantiating class
'org.quartz.myJob' [See nested exception:
java.lang.IllegalAccessException: Class
org.quartz.simpl.SimpleJobFactory can not access a member of class
org.quartz.myJob with modifiers ""]
at org.quartz.simpl.SimpleJobFactory.newJob(SimpleJobFactory.java:58)
at org.quartz.simpl.PropertySettingJobFactory.newJob(PropertySettingJobFactory.java:69)
at org.quartz.core.JobRunShell.initialize(JobRunShell.java:127)
at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:375)
Caused by: java.lang.IllegalAccessException: Class
org.quartz.simpl.SimpleJobFactory can not access a member of class
org.quartz.myJob with modifiers ""
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
at java.lang.Class.newInstance(Class.java:436)
at org.quartz.simpl.SimpleJobFactory.newJob(SimpleJobFactory.java:56)
... 3 more [INFO] 28 Dec 03:03:30.013 PM
DefaultQuartzScheduler_QuartzSchedulerThread
[org.quartz.simpl.RAMJobStore]
All triggers of Job group1.myJob set to ERROR state.
Your job class has to be public. Otherwise, the JobBuilder can not read it.
public class myJob implements Job {
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("Hello! HelloJob is executing.");
}
}
Class should be public class
Default constructor should be public
Improvement on top of the solution above. The class can be marked with static keyword to improve the efficiency. The job will be created each time when the scheduled slot occured.
public static class MyJob implements Job {
#Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("My job is called");
}
}
Related
I want to create a daily background job to be executed by AEM.
I read an aem document and apache sling official site, and I thought I need two classes.
a service class that register the job to JobManager.
a consumer class that do the job.
So I tried these code, but my job was not executed.
service class
import org.apache.sling.event.jobs.JobManager;
import org.apache.sling.event.jobs.JobBuilder.ScheduleBuilder;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
#Component
public class MyJobService {
private static final Logger logger = LoggerFactory.getLogger(MyJobService.class);
#Reference
private JobManager jobManager;
public static final String JOB_TOPIC = "my/sample/jobtopic";
public void startScheduledJob() {
ScheduleBuilder scheduleBuilder = jobManager.createJob(JOB_TOPIC).schedule();
scheduleBuilder.hourly(9, 0); // execute daily at AM9:00
if (scheduleBuilder.add() == null) {
logger.error("myjobservice error");
}
}
}
job consumer class
import org.apache.sling.event.jobs.Job;
import org.apache.sling.event.jobs.consumer.JobConsumer;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
#Component(
immediate = true,
service = JobConsumer.class,
property = {
JobConsumer.PROPERTY_TOPICS + "=my/sample/jobtopic"
}
)
public class MyJobConsumer implements JobConsumer {
private static final Logger logger = LoggerFactory.getLogger(MyJobConsumer.class);
#Override
public JobResult process(Job job) {
String topic = job.getTopic();
logger.info("this message is from myjobconsumer. topic is " + topic);
return JobResult.OK;
}
}
Do I need another class or some configurations? Does My code have something wrong?
If you annotate a method with #Activate it will be called when the component starts.
#Activate
public void startScheduledJob()
I guess you want your job to run on startup.
Another option would be to let MyJobService be a servlet and call it from outside.
I'm creating a simple cron job that run a task in a specific time (for example 3AM) with Play Framework 2.6.x.
But now I'm stucking in a simple schedule task:
I created an Actor:
package actors;
import akka.actor.UntypedActor;
import org.slf4j.LoggerFactory;
public class DoSomethingActor extends UntypedActor {
private static final org.slf4j.Logger log = LoggerFactory.getLogger(DoSomethingActor.class);
#Override
public void onReceive(final Object message) throws Throwable {
log.info("Write your crone task or simply call your method here that perform your task " + message);
}
}
Then I created a Schedule class that call Actor each time I've set:
package tasks;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Cancellable;
import scala.concurrent.duration.Duration;
#Singleton
public class DoSomethingScheduler {
#Inject
public DoSomethingScheduler(final ActorSystem system,
#Named("do-something-actor") final ActorRef doSomethingActor) {
final Cancellable scheduler;
final int timeDelayFromAppStart = 0;
final int timeGapInSeconds = 1; //Here you provide the time delay for every run
system.scheduler().schedule(
Duration.create(timeDelayFromAppStart, TimeUnit.MILLISECONDS), //Initial delay when system start
Duration.create(timeGapInSeconds, TimeUnit.SECONDS), //Frequency delay for next run
doSomethingActor,
"message for onreceive method of doSomethingActor",
system.dispatcher(),
null);
}
}
Finally, I bind these class in a Module class:
package modules;
import actors.DoSomethingActor;
import com.google.inject.AbstractModule;
import play.libs.akka.AkkaGuiceSupport;
import tasks.DoSomethingScheduler;
public class SchedulerModule extends AbstractModule implements AkkaGuiceSupport{
#Override
protected void configure() {
this.bindActor(DoSomethingActor.class, "do-something-actor");
this.bind(DoSomethingScheduler.class).asEagerSingleton();
}
}
After these things, I run the application but it doesn't work as I expected. I expected it shows a logging every 1 SECOND but there is nothing happen.
Could you please help me to fix it?
Thank you so much!
The solution is in dev mode, I have to send a HTTP request to the application to load the module. In production mode, they will be loaded immediately.
According to Quratz documentation2.x Here
If you add setter methods to your job class that correspond to the names of keys in the JobDataMap (such as a setJobSays(String val) method for the data in the example above), then Quartz’s default JobFactory implementation will automatically call those setters when the job is instantiated, thus preventing the need to explicitly get the values out of the map within your execute method.
Now in my case the setters are not automatically called although my all values are primitives. Also in execute method i am able to get values from jobDataMap.
i am using Quartz 2.2.1 and here is my sample code.what should i do ? thanks in advance.
Here is my Job class.
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution;
#PersistJobDataAfterExecution
#DisallowConcurrentExecution
public class Db2Db implements Job {
public static final String SOURCE_HOST = "sourceHost";
public static final String DESTINATION_HOST = "destinationHost";
protected String sourceHost;
protected String destinationHost;
public Db2Db() {
System.out.println("created object of job");
}
#Override
public void execute(JobExecutionContext context) throws JobExecutionException {
//sourceHost is still null
system.out.println(sourceHost);
}
public void setSourceHost(String sourceHost) {
this.sourceHost = sourceHost;
}
public void setDestinationHost(String destinationHost) {
this.destinationHost= destinationHost;
}
}
and Here is my main method
public class JobDriver {
public static void main(String[] args) throws SchedulerException {
/*Starting quartz server remotely*/
QuartzServer server = QuartzServer.getInstance();
server.start();
JobDetail job = newJob(Db2Db.class)
.usingJobData(SOURCE_HOST, "132.168.0.12")
.usingJobData(DESTINATION_HOST, "localhost")
.withIdentity("DailyRead91", "group1")
.build();
Trigger trigger = newTrigger().withIdentity("DailyTrigger91", "group1").startNow()
.withSchedule(simpleSchedule().withIntervalInSeconds(10).repeatForever()).build();
//Quartz Server Properties
Properties prop = new Properties();
prop.put("org.quartz.scheduler.rmi.proxy", "true");
prop.put("org.quartz.scheduler.rmi.registryHost", "localhost");
prop.put("org.quartz.scheduler.rmi.registryPort", "1099");
prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
prop.put("org.quartz.threadPool.threadCount", "10");
Scheduler scheduler = new StdSchedulerFactory(prop).getScheduler();
scheduler.scheduleJob(job, trigger);
}
}
I’m trying to create a task scheduler. I use Quartz. I followed this example.
I make the dependence in maven (tested 2.2.1 and 2.2.2) and my class HelloJob implements Job.
I have
public class HelloJob implements Job{
public void execute(JobExecutionContext context) throws JobExecutionException {
// Say Hello to the World and display the date/time
System.out.println("Hello World! - " + new Date());
JobDetail job = newJob(HelloJob.class)
.withIdentity("job1", "group1")
.build();
}
}
But I have the message:
The method newJob(Class<HelloJob>) is undefined for the type HelloJob
I tried to put the JobDetail declaration in my SimpleExample class, but the same error appears...
The method newJob is defined in org.quartz.JobBuilder as static. Add an static import in your class:
import static org.quartz.JobBuilder.*;
I Have a Spring project. It works fine with junit test case. juint calls the applicationcontext.xml and the project run successfully. But i want to run the project without using jUnit.
Here is my jUnit Test Case
package com.dataload;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.util.StopWatch;
#ContextConfiguration(locations = "classpath:com/dataload/applicationcontext.xml")
#RunWith(SpringJUnit4ClassRunner.class)
#TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
public class SICSVDataTestCase {
private final static Logger logger = Logger
.getLogger(SICSVDataTestCase.class);
#Autowired
private JobLauncher launcher;
#Autowired
private Job job;
private JobParameters jobParameters = new JobParameters();
#Test
public void testLaunchJob() throws Exception {
StopWatch sw = new StopWatch();
sw.start();
launcher.run(job, jobParameters);
sw.stop();
logger.info(">>> TIME ELAPSED:" + sw.prettyPrint());
}
}
This testcase run the project. But i want to use another class that can call the applicationcontext.xml and run the project.
That is,
package com.dataload;
public class insertCSV
{
public static void main(String args[])
{
/* Code to run the project */
}
}
Can anyone suggest me how to code? Thanks
Add this at the start of main
ApplicationContext context = new ClassPathXmlApplicationContext("path/to/applicationContext.xml");
JobLauncher launcher=(JobLauncher)context.getBean("launcher");
Job job=(Job)context.getBean("job");
//Get as many beans you want
//Now do the thing you were doing inside test method
StopWatch sw = new StopWatch();
sw.start();
launcher.run(job, jobParameters);
sw.stop();
//initialize the log same way inside main
logger.info(">>> TIME ELAPSED:" + sw.prettyPrint());
I am using in the way and it is working for me.
public static void main(String[] args) {
new CarpoolDBAppTest();
}
public CarpoolDBAppTest(){
ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
Student stud = (Student) context.getBean("yourBeanId");
}
Here Student is my classm you will get the class matching yourBeanId.
Now work on that object with whatever operation you want to do.
package com.dataload;
public class insertCSV
{
public static void main(String args[])
{
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationcontext.xml");
// retrieve configured instance
JobLauncher launcher = context.getBean("laucher", JobLauncher.class);
Job job = context.getBean("job", Job.class);
JobParameters jobParameters = context.getBean("jobParameters", JobParameters.class);
}
}