/**
* JBoss, Home of Professional Open Source
* Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual
* contributors by the @authors tag. See the copyright.txt in the
* distribution for a full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.seam.cron.asynchronous.threads;
import java.util.UUID;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import javax.enterprise.inject.spi.BeanManager;
import javax.inject.Inject;
import org.jboss.seam.cron.impl.asynchronous.exception.AsynchronousMethodInvocationException;
import org.jboss.seam.cron.impl.scheduling.exception.CronProviderDestructionException;
import org.jboss.seam.cron.impl.scheduling.exception.CronProviderInitialisationException;
import org.jboss.seam.cron.spi.CronProviderLifecycle;
import org.jboss.seam.cron.spi.asynchronous.CronAsynchronousProvider;
import org.jboss.seam.cron.spi.asynchronous.Invoker;
import org.jboss.seam.cron.spi.asynchronous.support.FutureInvokerSupport;
import org.jboss.solder.logging.Logger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerUtils;
import org.quartz.impl.DirectSchedulerFactory;
import org.quartz.simpl.RAMJobStore;
import org.quartz.simpl.SimpleThreadPool;
import org.quartz.spi.JobStore;
import org.quartz.spi.ThreadPool;
/**
* Simple asynchronous method invocation which schedules @Asynchronous methods
* to be executed at some point in the very near future using the Quartz scheduler.
*
* @author Peter Royle
*/
public class QuartzAsynchronousProvider implements CronProviderLifecycle, CronAsynchronousProvider {
/**
* The name of the job group for all arbitrarily scheduled events.
*/
public static final String ASYNC_JOB_GROUP = "async_job_group";
public static final String INV_CONTEXT_EXECUTOR = "inv_context_executor";
public static final String DELAYED_RESULT_SUPPORT = "future";
private static final String SCHEDULER_NAME_PREFIX = "SeamCronScheduler";
private String schedulerName;
private Scheduler scheduler;
private UUID instanceId;
private static final Logger log = Logger.getLogger(QuartzAsynchronousProvider.class);
@Inject
BeanManager beanManager;
/**
* Initialises the scheduler.
*
*/
public void initProvider() throws CronProviderInitialisationException {
try {
instanceId = UUID.randomUUID();
JobStore jobStore = new RAMJobStore();
ThreadPool threadPool = new SimpleThreadPool(4, Thread.NORM_PRIORITY);
threadPool.initialize();
final DirectSchedulerFactory schedulerFactory = DirectSchedulerFactory.getInstance();
schedulerName = SCHEDULER_NAME_PREFIX + "_" + instanceId.toString();
schedulerFactory.createScheduler(schedulerName, instanceId.toString(), threadPool, jobStore);
scheduler = schedulerFactory.getScheduler(schedulerName);
scheduler.start();
} catch (SchedulerException ex) {
throw new CronProviderInitialisationException("Error initialising Quartz for asynchronous method invocation");
}
}
/**
* Shutdown the scheduler on application close.
*/
public void destroyProvider() throws CronProviderDestructionException {
try {
scheduler.shutdown();
} catch (SchedulerException ex) {
log.warn("Error shutting down scheduler", ex);
}
}
public void executeWithoutReturn(final String queueId, final Invoker inkover) {
executeMethodAsScheduledJob(inkover);
}
public Future executeAndReturnFuture(final String queueId, final Invoker invoker) {
FutureTask asyncResult = new FutureTask(executeMethodAsScheduledJob(invoker));
new Thread(asyncResult).start();
return asyncResult;
}
private FutureInvokerSupport executeMethodAsScheduledJob(final Invoker invoker) throws AsynchronousMethodInvocationException {
final FutureInvokerSupport drs = new FutureInvokerSupport(invoker);
try {
final String name = UUID.randomUUID().toString();
JobDetail jobDetail = new JobDetail(name, ASYNC_JOB_GROUP, AsyncMethodInvocationJob.class);
jobDetail.getJobDataMap().put(DELAYED_RESULT_SUPPORT, drs);
scheduler.scheduleJob(jobDetail, TriggerUtils.makeImmediateTrigger(name, 0, 1));
} catch (SchedulerException ex) {
throw new AsynchronousMethodInvocationException("Error invoking method asynchronously", ex);
}
return drs;
}
}