3

My goal is starting JSR-352 batch jobs through a Quartz scheduler on a GlassFish server, but there's a big issue. First of all, here's my code.

My JSR-352 job:

<job id="myJob" ...>
    <step id="myBatchlet">
        <batchlet ref="mypackage.MyBatchlet" />
    </step>
</job>

The corresponding Java code:

public class MyBatchlet implements Batchlet {

    @Override
    public String process() throws Exception {
        System.out.println("Hello World!");
        return BatchStatus.COMPLETED.toString();
    }

    @Override
    public void stop() throws Exception {
    }

}

When I start this job on a GlassFish 4.0 b89 server via a servlet, it works perfectly:

public class StartJobServlet extends HttpServlet {

    private void processRequest(...) throws ... {
        long executionId = BatchRuntime.getJobOperator().start("myJob", new Properties());
        System.out.println("myJob started, execution ID = " + executionId);
    }

}

But now I want to use a Quartz 2.2.3 scheduler, so I've written a Quartz job this way:

public class StartMyJob implements Job {

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        long executionId = BatchRuntime.getJobOperator().start("myJob", new Properties());
        System.out.println("myJob started, execution ID = " + executionId);
    }

}

and I've configured Quartz and a trigger for this job.

But when myJob is supposed to be started, it remains in STARTING state and never actually runs.
According to the logs, the com.ibm.jbatch.container.util.BatchWorkUnit::run procedure which actually launches the batch job, is never called whereas it is when using a servlet.

EDIT: I've found someone else's similar issue (same symptoms) there, but the given solution can't fit since I have no glassfish-web.xml file.

hyuil
  • 33
  • 4
  • It looks more like a thread pool issue than a classloader issue. Since your job runs fine from your servlet, then it seems like an issue with the path coming from Quartz, (assuming you haven't changed the thread pool config). I'm not too familiar with Quartz in Glassfish, maybe you could share some details about how you are getting your Quartz job control in the server (e.g. is Quartz running in the server or remotely?). – Scott Kurz Jun 15 '17 at 10:40
  • Yes, I recreated the same thing. Will respond more if I come with anything. – Scott Kurz Jun 16 '17 at 19:02
  • The reason my sample fails is that Quartz is using its own thread to start the JSR 352 job. What I think is happening is that A) Glassfish seems to use some flavor of the ManagedExecutorService to execute the job (which propogates EE context) but B) there is no EE context on the unmanaged thread Quartz is using. Not sure if it's worth diving deeper into Quartz and/or Glassfish config to fix this somehow OR if it's worth revisiting your use case (e.g. what are you getting out of Quartz vs. say EJB timers if you're going to be within an EE app anyway). Hope that helps somewhat. – Scott Kurz Jun 16 '17 at 19:33

1 Answers1

1

Using Quartz in such a way that it executes a job on an unmanaged thread within an EE server will lead to issues using a variety of EE APIs, including Java Batch (JSR 352).

You could use standard EE APIs such as ManagedScheduledExecutorService, @Schedule, etc. to replace Quartz. (There are plenty of tutorials, examples out there on this).

I'm not enough of an expert on Quartz to list the alternatives involving Quartz. It would seem that if you could get Quartz threads to run using the ManagedExecutorService, it would solve the problem. This JIRA suggests this was added to Terracotta Quartz, but I don't claim to be certain. Perhaps there is a way using open source Quartz as well, either running Quartz outside the server, (and coming in remotely to a managed thread like an EJB?, not sure), or even using a configuration option I'm not aware of.

If anyone can provide a better answer clarifying the Quartz options it would be helpful.

Scott Kurz
  • 4,985
  • 1
  • 18
  • 40