views:

25

answers:

2

I'm using Quartz Scheduler v1.8.3 and is integrated into Apache Tomcat v6.0.10, and hence scheduler is initialized from within servlet container. Jobs are also added/scheduled to scheduler from within Apache Tomcat.

I'm designing a JSP web front end page (quartzAdmin.jsp) from where I only want to see scheduler information like meta-data values, all job details along with its triggers, currently executing jobs, etc.

My question is, in order to get a handle to the scheduler, which one of the below 2 option is recommended:

Option 1: Getting handle by directly calling schedulerFactory.getScheduler()

SchedulerFactory sf = new StdSchedulerFactory();
Scheduler scheduler = sf.getScheduler();

Option 2: Getting handle by implementing singleton pattern

public class Quartz {

    private Quartz() {
    }

    private static Scheduler scheduler = null;

    public static Scheduler getScheduler() {
        if(scheduler == null) {
            SchedulerFactory sf = new StdSchedulerFactory();
            scheduler = sf.getScheduler();
        }
        return scheduler;
    }
}

Then in my quartzAdmin.jsp, just a call Quartz.getScheduler() would return a handle to the scheduler.

A: 

What you are describing here is a singleton pattern, and your singleton initialization is not thread-safe.

I would recommend not using singleton here, but instead add a reference to Quartz to ServletContext, possibly initializing it in ServletContextListener.

web.xml

<listener>
  <listener-class>my.package.MyServletContextListener</listener-class>
</listener>

MyServletContextListener.java

package my.package;

public class MyServletContextListener implements ServletContextListener
{
    @Override
    public final void contextInitialized (
            final ServletContextEvent event
        )
    {
        final ServletContext servlet_ctx = event.getServletContext( );

        Quartz quartz = new Quartz( );

        servlet_ctx.addAttribute( Quartz.ATTRIBUTE_NAME, quartz );
    }

    @Override
    public void contextDestroyed (
            final ServletContextEvent event
        )
    {
        final ServletContext servlet_ctx = event.getServletContext( );

        Quartz.fromContext( servlet_ctx ).shutdown( );

        servlet_ctx.removeAttribute( Quartz.ATTRIBUTE_NAME );
    }
}

Quartz.java

public final static String ATTRIBUTE_NAME = Quartz.class.getName( );

public Quartz( )
{
    ...
}

public static Quartz fromContext( final ServletContext ctx )
{
  return ctx.getAttribute( ATTRIBUTE_NAME );
}

public void shutdown( )
{
    ...
}
Alexander Pogrebnyak
@Alexander: Assuming I don't manipulate anything with scheduler apart from just getting scheduler related information, is it still should be made thread-safe? Hope you meant "not thread-safe" in this context, am I right? Also, I'm not able to clearly understand your recommendation mentioned. Can you explain with some simple code sample?
Gnanam
@Gnanam. If you intend to call your original getScheduler( ) method directly from JSP ( not recommended ) it will most definitely be called from multiple threads. Check this post for correct way to initialize singleton: http://stackoverflow.com/questions/3635396/pattern-for-lazy-thread-safe-singleton-instantiation-in-java/3635619#3635619
Alexander Pogrebnyak
A: 

I think what both options do is create a new Scheduler, not getting the one you have configured in web.xml.

Currently I am doing this (similar to Option 1):

...configure a QuartzInitializerListener for my webapp...
// my servlet's init()
public void init(ServletConfig config) throws ServletException {
    ...
    SchedulerFactory factory =
            (SchedulerFactory) config.getServletContext().getAttribute(
                QuartzInitializerListener.QUARTZ_FACTORY_KEY
            );
    Scheduler factory.getScheduler();
    ...
}
gpeche
@gpeche: No, I'm getting a handle to the scheduler which was initialized before from `web.xml`. I can verify this using `scheduler.getMetaData().getSummary()` and check for this line `Running since: xxxxx`
Gnanam
@gpeche: I believe that this is already taken care by Quartz scheduler itself.
Gnanam
Well, then there is no need to use a singleton as Quartz is taking care of that. Just use option 1.
gpeche