Quartz.Net embedded into Asp.NET MVC2, not firing off jobs - asp.net

I'm trying to get Quartz.net working by embedding into my .Net MVC2 application. I know this is not ideal, but I'm just trying to get it up and running before moving it over to a service. I can't get my jobs to fire off, but I think I'm configured correctly. In my Global.asax.cs:
protected void Application_Start()
{
Quartz.IScheduler scheduler = BuildQuartzScheduler();
...
}
And the method, taken straight from the tutorial:
private IScheduler BuildQuartzScheduler()
{
// construct a scheduler factory
ISchedulerFactory schedFact = new StdSchedulerFactory();
// get a scheduler
IScheduler sched = schedFact.GetScheduler();
sched.Start();
// construct job info
JobDetail jobDetail = new JobDetail("myJob", null, typeof(QuartzController));
// fire every hour
Trigger trigger = TriggerUtils.MakeMinutelyTrigger();
// start on the next even hour
trigger.StartTimeUtc = TriggerUtils.GetEvenMinuteDate(DateTime.UtcNow);
trigger.Name = "myTrigger";
sched.ScheduleJob(jobDetail, trigger);
return sched;
}
And the "controller:"
public class QuartzController : IJob
{
public QuartzController() {
}
public void Execute(JobExecutionContext context) {
throw new NotImplementedException();
}
}
Nothing ever gets fired. What's going on? I'm sure there must be a simple syntax mistake, but it is driving me crazy!

If Application_Start looks like that, then I reckon your scheduler variable is likely to be garbage collected as soon as that method finishes executing.
I'd store a reference to the scheduler as a static variable in your HttpApplication class. This way, the reference hangs around for the duration of the process. A guess, but worth a shot.

Related

How to activate RequestScope inside CompletableFuture (getting org.jboss.weld.context.ContextNotActiveException) [duplicate]

I could not find a definitive answer to whether it is safe to spawn threads within session-scoped JSF managed beans. The thread needs to call methods on the stateless EJB instance (that was dependency-injected to the managed bean).
The background is that we have a report that takes a long time to generate. This caused the HTTP request to time-out due to server settings we can't change. So the idea is to start a new thread and let it generate the report and to temporarily store it. In the meantime the JSF page shows a progress bar, polls the managed bean till the generation is complete and then makes a second request to download the stored report. This seems to work, but I would like to be sure what I'm doing is not a hack.
Check out EJB 3.1 #Asynchronous methods. This is exactly what they are for.
Small example that uses OpenEJB 4.0.0-SNAPSHOTs. Here we have a #Singleton bean with one method marked #Asynchronous. Every time that method is invoked by anyone, in this case your JSF managed bean, it will immediately return regardless of how long the method actually takes.
#Singleton
public class JobProcessor {
#Asynchronous
#Lock(READ)
#AccessTimeout(-1)
public Future<String> addJob(String jobName) {
// Pretend this job takes a while
doSomeHeavyLifting();
// Return our result
return new AsyncResult<String>(jobName);
}
private void doSomeHeavyLifting() {
try {
Thread.sleep(SECONDS.toMillis(10));
} catch (InterruptedException e) {
Thread.interrupted();
throw new IllegalStateException(e);
}
}
}
Here's a little testcase that invokes that #Asynchronous method several times in a row.
Each invocation returns a Future object that essentially starts out empty and will later have its value filled in by the container when the related method call actually completes.
import javax.ejb.embeddable.EJBContainer;
import javax.naming.Context;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class JobProcessorTest extends TestCase {
public void test() throws Exception {
final Context context = EJBContainer.createEJBContainer().getContext();
final JobProcessor processor = (JobProcessor) context.lookup("java:global/async-methods/JobProcessor");
final long start = System.nanoTime();
// Queue up a bunch of work
final Future<String> red = processor.addJob("red");
final Future<String> orange = processor.addJob("orange");
final Future<String> yellow = processor.addJob("yellow");
final Future<String> green = processor.addJob("green");
final Future<String> blue = processor.addJob("blue");
final Future<String> violet = processor.addJob("violet");
// Wait for the result -- 1 minute worth of work
assertEquals("blue", blue.get());
assertEquals("orange", orange.get());
assertEquals("green", green.get());
assertEquals("red", red.get());
assertEquals("yellow", yellow.get());
assertEquals("violet", violet.get());
// How long did it take?
final long total = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start);
// Execution should be around 9 - 21 seconds
assertTrue("" + total, total > 9);
assertTrue("" + total, total < 21);
}
}
Example source code
Under the covers what makes this work is:
The JobProcessor the caller sees is not actually an instance of JobProcessor. Rather it's a subclass or proxy that has all the methods overridden. Methods that are supposed to be asynchronous are handled differently.
Calls to an asynchronous method simply result in a Runnable being created that wraps the method and parameters you gave. This runnable is given to an Executor which is simply a work queue attached to a thread pool.
After adding the work to the queue, the proxied version of the method returns an implementation of Future that is linked to the Runnable which is now waiting on the queue.
When the Runnable finally executes the method on the real JobProcessor instance, it will take the return value and set it into the Future making it available to the caller.
Important to note that the AsyncResult object the JobProcessor returns is not the same Future object the caller is holding. It would have been neat if the real JobProcessor could just return String and the caller's version of JobProcessor could return Future<String>, but we didn't see any way to do that without adding more complexity. So the AsyncResult is a simple wrapper object. The container will pull the String out, throw the AsyncResult away, then put the String in the real Future that the caller is holding.
To get progress along the way, simply pass a thread-safe object like AtomicInteger to the #Asynchronous method and have the bean code periodically update it with the percent complete.
Introduction
Spawning threads from within a session scoped managed bean is not necessarily a hack as long as it does the job you want. But spawning threads at its own needs to be done with extreme care. The code should not be written that way that a single user can for example spawn an unlimited amount of threads per session and/or that the threads continue running even after the session get destroyed. It would blow up your application sooner or later.
The code needs to be written that way that you can ensure that an user can for example never spawn more than one background thread per session and that the thread is guaranteed to get interrupted whenever the session get destroyed. For multiple tasks within a session you need to queue the tasks.
Also, all those threads should preferably be served by a common thread pool so that you can put a limit on the total amount of spawned threads at application level.
Managing threads is thus a very delicate task. That's why you'd better use the built-in facilities rather than homegrowing your own with new Thread() and friends. The average Java EE application server offers a container managed thread pool which you can utilize via among others EJB's #Asynchronous and #Schedule. To be container independent (read: Tomcat-friendly), you can also use the Java 1.5's Util Concurrent ExecutorService and ScheduledExecutorService for this.
Below examples assume Java EE 6+ with EJB.
Fire and forget a task on form submit
#Named
#RequestScoped // Or #ViewScoped
public class Bean {
#EJB
private SomeService someService;
public void submit() {
someService.asyncTask();
// ... (this code will immediately continue without waiting)
}
}
#Stateless
public class SomeService {
#Asynchronous
public void asyncTask() {
// ...
}
}
Asynchronously fetch the model on page load
#Named
#RequestScoped // Or #ViewScoped
public class Bean {
private Future<List<Entity>> asyncEntities;
#EJB
private EntityService entityService;
#PostConstruct
public void init() {
asyncEntities = entityService.asyncList();
// ... (this code will immediately continue without waiting)
}
public List<Entity> getEntities() {
try {
return asyncEntities.get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new FacesException(e);
} catch (ExecutionException e) {
throw new FacesException(e);
}
}
}
#Stateless
public class EntityService {
#PersistenceContext
private EntityManager entityManager;
#Asynchronous
public Future<List<Entity>> asyncList() {
List<Entity> entities = entityManager
.createQuery("SELECT e FROM Entity e", Entity.class)
.getResultList();
return new AsyncResult<>(entities);
}
}
In case you're using JSF utility library OmniFaces, this could be done even faster if you annotate the managed bean with #Eager.
Schedule background jobs on application start
#Singleton
public class BackgroundJobManager {
#Schedule(hour="0", minute="0", second="0", persistent=false)
public void someDailyJob() {
// ... (runs every start of day)
}
#Schedule(hour="*/1", minute="0", second="0", persistent=false)
public void someHourlyJob() {
// ... (runs every hour of day)
}
#Schedule(hour="*", minute="*/15", second="0", persistent=false)
public void someQuarterlyJob() {
// ... (runs every 15th minute of hour)
}
#Schedule(hour="*", minute="*", second="*/30", persistent=false)
public void someHalfminutelyJob() {
// ... (runs every 30th second of minute)
}
}
Continuously update application wide model in background
#Named
#RequestScoped // Or #ViewScoped
public class Bean {
#EJB
private SomeTop100Manager someTop100Manager;
public List<Some> getSomeTop100() {
return someTop100Manager.list();
}
}
#Singleton
#ConcurrencyManagement(BEAN)
public class SomeTop100Manager {
#PersistenceContext
private EntityManager entityManager;
private List<Some> top100;
#PostConstruct
#Schedule(hour="*", minute="*/1", second="0", persistent=false)
public void load() {
top100 = entityManager
.createNamedQuery("Some.top100", Some.class)
.getResultList();
}
public List<Some> list() {
return top100;
}
}
See also:
Spawning threads in a JSF managed bean for scheduled tasks using a timer
I tried this and works great from my JSF managed bean
ExecutorService executor = Executors.newFixedThreadPool(1);
#EJB
private IMaterialSvc materialSvc;
private void updateMaterial(Material material, String status, Location position) {
executor.execute(new Runnable() {
public void run() {
synchronized (position) {
// TODO update material in audit? do we need materials in audit?
int index = position.getMaterials().indexOf(material);
Material m = materialSvc.getById(material.getId());
m.setStatus(status);
m = materialSvc.update(m);
if (index != -1) {
position.getMaterials().set(index, m);
}
}
}
});
}
#PreDestroy
public void destory() {
executor.shutdown();
}

Multithreading using Callable while having a responsive graphical interface

I'm trying to get a responsive JavaFX graphical interface while executing a cmd command.
The command I'm executing is the following.
youtube-dl.exe --audio-format mp3 --extract-audio https://www.youtube.com/watch?v=l2vy6pJSo9c
As you see this is a youtube-downloader that converts a youtube link to an mp3-file.
I want this to be executed in a second thread and not in the main FX thread.
I've solved this by implementing interface Callable in the class StartDownloadingThread.
#Override
public Process call() throws Exception {
Process p = null;
p = ExecuteCommand(localCPara1, localCPara2, localDirectory).start();
try {
Thread.sleep(30);
}catch (InterruptedException e){}
return p;
}
The method ExecuteCommand just returns a ProcessBuilder object.
I try to use Thread.sleep to make the program return to the main thread and thus making the application responsive. Unfortunately the program still freezes.
This is how the method call is called.
ExecutorService pool = Executors.newFixedThreadPool(2);
StartDownloadingThread callable = new StartDownloadingThread(parameter1, parameter2, directory);
Future future = pool.submit(callable);
Process p = (Process) future.get();
p.waitFor();
How do I make my GUI responsive using the interface Callable?
Using a executor to run a task just for you to use the get method of the Future that is returned when submitting the task does not actually free the original thread to continue with other tasks. Later you even use the waitFor method on the original thread, which is likely to take even more time than anything you do in your Callable.
For this purpose the Task class may be better suited, since it allows you to handle success/failure on the application thread using event handlers.
Also please make sure an ExecutorService is shut down after you're done submitting tasks.
Task<Void> task = new Task<Void>() {
#Override
protected Void call() throws Exception {
Process p = null;
p = ExecuteCommand(localCPara1, localCPara2, localDirectory).start();
// why are you even doing this?
try {
Thread.sleep(30);
}catch (InterruptedException e){}
// do the rest of the long running things
p.waitFor();
return null;
}
};
task.setOnSucceeded(event -> {
// modify ui to show success
});
task.setOnFailed(event -> {
// modify ui to show failure
});
ExecutorService pool = Executors.newFixedThreadPool(2);
pool.submit(task);
// add more tasks...
// shutdown the pool not keep the jvm alive because of the pool
pool.shutdown();

Quartz.NET can invoke my class function if asp.net app pool is idle

suppose i wrote & schedule Quartz.NET job related code in application_start event like this way
public class HelloJob : IJob
{
public void Execute(JobExecutionContext context)
{
//Send Mail
}
}
public static void ConfigureQuartzJobs()
{
// construct a scheduler factory
ISchedulerFactory schedFact = new StdSchedulerFactory();
// get a scheduler
IScheduler sched = schedFact.GetScheduler();
sched.Start();
// construct job info
JobDetail jobDetail = new JobDetail("myJob", null, typeof(HelloJob));
//created trigger which will fire every minute starting immediately
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("myTrigger", "group1")
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(60)
.RepeatForever())
.Build();
sched.ScheduleJob(jobDetail, trigger);
}
protected void Application_Start()
{
ConfigureQuartzJobs();
}
so i like to know that my routine will hit after every 60 second if app pool is idle or if no visitor is browsing my web site any page?
my main concern is i need to invoke a specific routine after 60 second if app pool is idle or active. or even no visitor is browsing my web site any page.
so please guide me what should i do? thanks
You can do following without Quartz:
1) In Application_End method check shutdown reason (you are interested in timeout).
http://msdn.microsoft.com/en-us/library/system.web.applicationshutdownreason(v=vs.110).aspx
2) When you get the idle timeout reason write and event with specific id to windows event log
3) Go to windows task scheduler. Create new task. Go to triggers. New trigger. in the trigger type combo box choose "On an event". Choose the log, source and event id you write to log. (by default Application)
4) Go to Actions->New->Send Email

Configuring Quartz.Net to stop a job from executing, if it is taking longer than specified time span

I am working on making a scheduler, just like Windows Scheduler using Quartz.Net.
In Windows Scheduler, there is an option to stop a task from running if it takes more than the specified time. I have to implement the same in my scheduler.
But I am not able to find any extension method/setting to configure Trigger or Job accordingly.
I request some inputs or suggestions for it.
You can write small code to set a custom timout running on another thread. Implement IInterruptableJob interface and make a call to its Interrupt() method from that thread when the job should be interrupted. You can modify the following sample code as per your need. Please make necessary checks/config inputs wherever required.
public class MyCustomJob : IInterruptableJob
{
private Thread runner;
public void Execute(IJobExecutionContext context)
{
int timeOutInMinutes = 20; //Read this from some config or db.
TimeSpan timeout = TimeSpan.FromMinutes(timeOutInMinutes);
//Run your job here.
//As your job needs to be interrupted, let us create a new task for that.
var task = new Task(() =>
{
Thread.Sleep(timeout);
Interrupt();
});
task.Start();
runner = new Thread(PerformScheduledWork);
runner.Start();
}
private void PerformScheduledWork()
{
//Do what you wish to do in the schedled task.
}
public void Interrupt()
{
try
{
runner.Abort();
}
catch (Exception)
{
//log it!
}
finally
{
//do what you wish to do as a clean up task.
}
}
}

Reoccurring timer in Asp.net

I am trying to implement a reoccurring timer function asp.net. I am not able to create a windows service as I host the site on a shared environment and therefore do not have access.
I have read various ways of achieving this each with their own advantages/disadvantages. The cache object approach seemed promising but does seem like a hack.
I have been trying to implement a httphandler that will spin up a single System.Threading.Timer object to cycle every minute and do some work. Possibly queuing up other work items.
Here is what I have so far:
public class Scheduler : IHttpHandler
{
protected static TimerCallback tcb = null;
protected static Timer timer = null;
static Scheduler()
{
tcb = new TimerCallback(DoWork);
timer = new Timer(tcb, null, TimeSpan.Zero, new TimeSpan(0, 0, 1, 0));
}
private static void DoWork(Object stateInfo)
{
}
public void ProcessRequest(HttpContext context)
{
}
public bool IsReusable
{
get { return false; }
}
}
I read here that you need to mindful of the timer not being disposed of when the appDomain unloading. He does imply that it is only a problem if you are invoking native code which I am not. I couldn't figure out how to tie into the application_end event to dispose of the timer from within the handler.
My question is, Is the above approach way off the mark? Is there a better way to do this? Would it make more sense to ditch the static variables and store the timer in application state?
Sorry I need informed opinions. I feel like i'm going around in circles.
Thanks,
This is a complete hack, hope I don't get down voted! - but you could develop a component which is part of your web deployment which makes an Http request to a handler on the same site - this way (I guess) your app would be able to call itself to ensure it wasn't unloaded. see the WebClient class - sorry not sure which namespace off the top of my head.
If you do this you'll need to think about how it's restarted if it's taken down for any reason; and I'm not sure if you'll get any weird behaviour if you have a web application that stays up for really long periods of time.

Resources