0

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.

Charles
  • 50,943
  • 13
  • 104
  • 142
Gnanam
  • 10,613
  • 19
  • 54
  • 72
  • A related question on initializing quartz: http://stackoverflow.com/questions/3257074/whats-the-best-way-to-initalize-quartz – Gnanam Sep 08 '10 at 13:56

2 Answers2

0

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
  • 44,836
  • 10
  • 105
  • 121
  • 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 Sep 08 '10 at 14:10
  • 1
    @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 Sep 08 '10 at 16:41
0

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
  • 21,974
  • 5
  • 38
  • 51
  • 1
    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 Sep 08 '10 at 14:02
  • I believe that this is already taken care by Quartz scheduler itself. – Gnanam Sep 08 '10 at 14:04
  • 1
    Well, then there is no need to use a singleton as Quartz is taking care of that. Just use option 1. – gpeche Sep 08 '10 at 14:21