How to get quartz scheduler end event - .net-4.5

I have a following code where i have started a quartz scheduler
internal static IScheduler MyQuartzScheduler = null;
private static async void StartProcessing()
{
try
{
Logger.Info("Starting Quartz");
StdSchedulerFactory factory = new StdSchedulerFactory();
MyQuartzScheduler = await factory.GetScheduler();
await MyQuartzScheduler.Start();
QuartzScedulerMessage = String.Format("Quart Scheduler Started on {0}", DateTime.Now);
}
catch (Exception ex)
{
QuartzScedulerMessage = ex.Message;
Logger.Fatal(ex.Message, ex);
}
}
My scheduler is started and working fine. I were just curious if for any reason (like i have ado job store in my sql and db connectivity break) if scheduler crashes .Any how i can get scheduler ending or crashing event?

I think you should try Scheduler Listener in Quartz.NET here is the documentation ;
Scheduler Listener

Related

#KafkaListener : behavior and tracking processing of events

We are using spring-kafka 2.3.0 in our app . Have observed some processing glitches in the scenarios below with
#Service
#EnableScheduling
public class KafkaService {
public void sendToKafkaProducer(String data) {
kafkaTemplate.send(configuration.getProducer().getTopicName(), data);
}
#KafkaListener(id = "consumer_grpA_id",
topics = "#{__listener.getEnvironmentConfiguration().getConsumer().getTopicName()}", groupId = "consumer_grpA", autoStartup = "false")
public void onMessage(ConsumerRecord<String, String> data) throws Exception {
passA(data);
}
private void passB(String message) {
//counter to keep track of retry attempts
if (counter.containsKey(message.getEventID())) {
//RETRY_COUNT = 5
if (counter.get(message.getEventID()) < RETRY_COUNT) {
retryAgain(message);
}
} else {
firstRetryPass(message);
}
}
private void retryAgain(String message) {
counter.put(message.getEventID(), counter.get(message.getEventID()) + 1);
try {
registry.stop(); //pause the listener
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void firstRetryPass(String message) {
// First Time Entry for count and time
counter.put(message.getEventID(), 1);
try {
registry.stop();//pause the listener
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void passA(String message) {
try {
passToTarget(message); //Call target processor
LOGGER.info("Message Processed Successfully to the target");
} catch (Exception e) {
targetUnavailable= true;
passB(message);
}
}
private void passToTarget(String message){
//processor logic, if the target is not available, retry after 15 mins, call passB func
}
#Scheduled(cron = "0 0/15 * 1/1 * ?")
public void scheduledMethod() {
try {
if (targetUnavailable) {
registry.start();
firstTimeStart = false;
}
LOGGER.info(">>>Scheduler Running ?>>>" + registry.isRunning());
} catch (Exception e) {
LOGGER.error(e.getMessage());
}
}
}
On receipt of the first message after a gap in processing, the consumer doesn't pick up the first message. The subsequent messages are processed.
As we don't have the direct access to Kafka topics, we aren't able to identify the process that didn't get picked up from consumer.
How do we track those events that arenot picked up and why is it so.?
We also configured a scheduler whose job is to keep the registry for Kafka running . So is this scheduler required when we already have a listener configured ?
What is the mem and CPU utilization metrics if we keep the listener running. That was one of the reason we used the Kafka registry to stop the listener explicitly whenever the target is down. So need to validate if this approach is sustainable. My hunch is this is against the basic working of Listener, as it's main job is to continue listening for new events irrespective of target status
Edited*
You shouldn't stop the registry on the listener thread unless you use stop(Runnable) - otherwise there will be a deadlock and a delay since the container waits for the listener to exit.
Stopping the container (via the registry) won't actually take effect until any remaining records fetched by the last poll have been processed (unless you set max.poll.records=1.
When the listener exits normally, the record's offset will be committed so that record will not be redelivered on the next start.
You can use the ContainerStoppingErrorHandler for this use case. See here.
Throw an exception and the error handler will stop the container for you.
But that will stop the container on the first try.
If you want retries, use a SeekToCurrentErrorHandler and call the ContainerStoppingErrorHandler from the recoverer after retries are exhausted.

How to do with Quartz put some trigger to one job?

public static void sendEmailForNewTrigger(String jobName, String triggerName, Date sendDate) {
try {
Scheduler sched = QuartzSchedulerManager.getInstanceScheduler();
JobKey jobKey = JobKey.jobKey(jobName, "group_email");
JobDetail job = sched.getJobDetail(jobKey);
SimpleTrigger trigger = (SimpleTrigger) newTrigger().withIdentity(triggerName)
.startAt(sendDate)
.build();
if (job == null) {
job = newJob(SendEmailJob.class).withIdentity(jobName, "group_email").build();
}
sched.scheduleJob(job, trigger);
log.info(jobName + " will run at: " + sendDate);
} catch (SchedulerException e) {
log.error(e.toString());
throw new RuntimeException(e.getMessage());
}
}
in my code ,it can't work, always tell me 'Unable to store Job : 'group_email.send_1', because one already exists with this identification.' i don't know how to do ,just want to add two or more trigger to one job.

Continually restating a job using JobExecutionListener

We need a job to run continuously without the need for an external scheduler.
I have extended JobExecutionListener, as follows:
#Autowired
#Qualifier("myJob")
private Job job;
private int counter = 0;
#Override
public void afterJob(JobExecution jobExecution) {
jobExecution.stop();
JobParameters jobParameters = new JobParameters();
JobParameter jobParameter = new JobParameter((new Integer(++counter)).toString());
jobParameters.getParameters().put("counter", jobParameter);
try {
jobLauncher.run(job, jobParameters);
}
catch (JobExecutionAlreadyRunningException e) {
throw new RuntimeException(e);
} catch (JobRestartException e) {
throw new RuntimeException(e);
} catch (JobInstanceAlreadyCompleteException e) {
throw new RuntimeException(e);
} catch (JobParametersInvalidException e) {
throw new RuntimeException(e);
}
When run, a JobExecutionAlreadyRunningException is thrown.
JobExecutionAlreadyRunningException: A job execution for this job is already running: JobInstance: id=0, version=0, Job=[myJob]
Where am I going wrong?
Thanks
From official doc:
The shutdown is not immediate, since there is no way to force
immediate shutdown, especially if the execution is currently in
developer code that the framework has no control over, such as a
business service. However, as soon as control is returned back to the
framework, it will set the status of the current StepExecution to
BatchStatus.STOPPED, save it, then do the same for the JobExecution
before finishing.
Maybe you can have a chance using a specialized JobLauncher that launch the job after previous job's thread termination or a custom TaskExecutor associated to JobLauncher.

Vert.x - Get deployment ID within currently running verticle

I'm looking for the deployment ID for the currently running verticle.
The goal is to allow a verticle to undeploy itself. I currently pass the deploymentID into the deployed verticle over the event bus to accomplish this, but would prefer some direct means of access.
container.undeployVerticle(deploymentID)
There are 2 ways you can get the deployment id. If you have some verticle that starts and handles all the module deployments you can add an async result handler and then get the deployment id that way or you can get the platform manager from the container using reflection.
Async handler will be as follows:
container.deployVerticle("foo.ChildVerticle", new AsyncResultHandler<String>() {
public void handle(AsyncResult<String> asyncResult) {
if (asyncResult.succeeded()) {
System.out.println("The verticle has been deployed, deployment ID is " + asyncResult.result());
} else {
asyncResult.cause().printStackTrace();
}
}
});
Access Platform Manager as follows:
protected final PlatformManagerInternal getManager() {
try {
Container container = getContainer();
Field f = DefaultContainer.class.getDeclaredField("mgr");
f.setAccessible(true);
return (PlatformManagerInternal)f.get(container);
}
catch (Exception e) {
e.printStackTrace();
throw new ScriptException("Could not access verticle manager");
}
}
protected final Map<String, Deployment> getDeployments() {
try {
PlatformManagerInternal mgr = getManager();
Field d = DefaultPlatformManager.class.getDeclaredField("deployments");
d.setAccessible(true);
return Collections.unmodifiableMap((Map<String, Deployment>)d.get(mgr));
}
catch (Exception e) {
throw new ScriptException("Could not access deployments");
}
}
References:
http://grepcode.com/file/repo1.maven.org/maven2/io.vertx/vertx-platform/2.1.2/org/vertx/java/platform/impl/DefaultPlatformManager.java#DefaultPlatformManager.genDepName%28%29
https://github.com/crashub/mod-shell/blob/master/src/main/java/org/vertx/mods/VertxCommand.java
http://vertx.io/core_manual_java.html#deploying-a-module-programmatically
Somewhere in your desired verticle use this:
context.deploymentID();

Quartz scheduler in not running in war

I am using quartz scheduler in gwt web application.My application structure is like below.
I have two project.One is gwt web application client project(for ui part) & other is java project for server side call.(for database interaction).In client project I put a server project for reference.While running I create a war from client and add a jar of server project to war folder.
Now I used scheduler at server side for some task to auto complete.While running it locally (with out war) scheduler working properly.
But while running war at jboss server scheduler is not running.
My all scheduler related code and Quartz.jar is at server side.There is no any reference of Quartz in client side project.is this the problem???
Here is my code for scheduler
public class QuartzJob implements Job {
public void execute(JobExecutionContext jobExecutionContext)
throws JobExecutionException {
JobDataMap map = jobExecutionContext.getJobDetail().getJobDataMap();
ActivityTransactionSettingsMap map2 = (ActivityTransactionSettingsMap) map
.get("task");
if (map2.getAutoCompleteDate() != null) {
WorkFlowFacade facade = new WorkFlowFacade();
facade.completeAutoCompleteTask(map2);
Scheduler scheduler=(Scheduler) map.get("scheduler");
try {
scheduler.shutdown();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
}
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
JobDataMap map2 = new JobDataMap();
map2.put("task", actsMap);
map2.put("scheduler", scheduler);
JobDetail job = newJob(QuartzJob.class).withIdentity("job"+String.valueOf(actsMap.getId()))
.usingJobData(map2).build();
Trigger trigger = newTrigger().withIdentity("trigger"+String.valueOf(actsMap.getId()))
.startAt(actsMap.getAutoCompleteDate()).build();
scheduler.scheduleJob(job, trigger);
Or do I need to shift my scheduler related project at client side only??
I am not getting how to solve this.
Please help me out
For the scheduler to run , there should be something to kick start it . I am not sure how the process is happening but you could write this scheduler in a servlet
public class MySchedulerServlet extends GenericServlet {
private static final long serialVersionUID = 1477091380142883153L;
/**
* Constant to represent property for the cron expression.
*/
private static final String CRON_EXPRESSION = "0 0 0 ? * SUN";
public void init(ServletConfig servletConfig) throws ServletException {
super.init(servletConfig);
// The Quartz Scheduler
Scheduler scheduler = null;
try {
// Initiate a Schedule Factory
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
// Retrieve a scheduler from schedule factory
scheduler = schedulerFactory.getScheduler();
// Initiate JobDetail with job name, job group and
// executable job class
JobDetail jobDetail = new JobDetail("RetryJob", "RetryGroup", QuartzJob.class);
// Initiate CronTrigger with its name and group name
CronTrigger cronTrigger = new CronTrigger("cronTrigger",
"triggerGroup");
// setup CronExpression
CronExpression cexp = new CronExpression(CRON_EXPRESSION);
// Assign the CronExpression to CronTrigger
cronTrigger.setCronExpression(cexp);
// schedule a job with JobDetail and Trigger
scheduler.scheduleJob(jobDetail, cronTrigger);
// start the scheduler
scheduler.start();
} catch (Exception e) {
e.printStackTrace();
}
}
public void service(ServletRequest serveletRequest,
ServletResponse servletResponse) throws ServletException, IOException {
}
}
and in your web.xml load sceduler on startup. This works for me.
<servlet>
<servlet-name>QuartzInitializer</servlet-name>
<servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class>
<init-param>
<param-name>shutdown-on-unload</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>start-scheduler-on-load</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-name>MySchedulerServlet </servlet-name>
<servlet-class>com.servlet.MySchedulerServlet </servlet-class>
<load-on-startup>2</load-on-startup>
I used thread in this case.
public class AutoCompleteTaskThread extends Thread {
private ActivityTransactionSettingsMap taskMap;
public AutoCompleteTaskThread(ActivityTransactionSettingsMap map) {
this.taskMap = map;
}
#Override
public void run() {
try {
new AutoCompleteTaskScheduler().ScheduleJob(taskMap);
} catch (Exception e) {
e.printStackTrace();
}
}
}
As below and in local machine it is working fine.but for jboss server it is not working.
I used an instance of AutoCompleteTaskThread class and called start method on this.
private void addAutoCompleteTask(ActivityTransactionSettingsMap newTask) {
AutoCompleteTaskThread thread = new AutoCompleteTaskThread(newTask);
thread.start();
}
Here for I started a thread for any new task for which I want to start new thread.