Search code examples
jakarta-eetransactionsejbquartz-schedulerjta

Quartz is not participating in EJB transactions (in CMT mode)


I integrated Quartz2.2.2 with my Java EE application which is running in Weblogic 12.1.2. I want to handle all JTA transactions with my container (Weblogic). But when an exception is occurred everything is rollbacked except for quartz transactions, I think the problem goes back to quartz.properties here is my config file:

org.quartz.scheduler.instanceName = MyScheduler
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreCMT
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.oracle.weblogic.WebLogicOracleDelegate
org.quartz.jobStore.dataSource = quartz
org.quartz.threadPool.threadCount = 3
org.quartz.jobStore.nonManagedTXDataSource = quartz
org.quartz.dataSource.quartz.jndiURL = java.weblogic.datasources.quartz

I set both managed transactions' datasource and nonManaged one to the same datasource and it seems to be wrong! But I couldn't understand why I should set nonManagedTXDataSource and this field is mandatory! In documentation of quartz web site it is suggested that:

JobStoreCMT requires a (second) datasource that contains connections that will not be part of container-managed transactions. The value of this property must be the name of one the DataSources defined in the configuration properties file. This datasource must contain non-CMT connections, or in other words, connections for which it is legal for Quartz to directly call commit() and rollback() on.

Why I need such a datasource when I want all my transactons to be managed by the container!

Code example:

@Stateless
public class MyServiceHandlerBean {

    @EJB
    MyObjectManager objManager;

    @EJB
    MyScheduler scheduler;

    public void addObj() throws MyException {
    MyObject obj = new MyObject("fname","lastname");
    objManager.save(obj);
    scheduler.addJobForObj(obj);
    }
}

and MyScheduler class that works with quartz:

@LocalBean
@Stateless
public class MyScheduler {

    private Scheduler scheduler = null;

    public MyScheduler() throws SchedulerException {
        scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.start();
    }

    public void addJobForObj(MyObject obj) throws MyException {
        JobBuilder jobBuilder = newJob(BaseJob.class).withIdentity(obj.getId());
        JobDetail job = jobBuilder.build();

    try {
        // Does something to create triggers
        scheduler.scheduleJob(job, triggers, false);
        } catch (SchedulerException e) {
           throw new MyException("Something");
        } catch (MyException e) {
            throw e;
        }
    }
 }

and here is MyException class code:

@ApplicationException(rollback=true)
public class MyException extends Exception{

}

The problem is when I call MyServiceHandlerBean method (addObj) when save operation of MyObjectManager fails container rolls transaction back but the job is added to the Database of quartz scheduler.


Solution

  • After a while I found that it was my mistake! Maybe this should be a comment but I think it can be more useful if I post it as an answer. My mistake was in the Weblogic data-source configuration. I should have enabled Support Global Transaction in the data-source transaction configuration.