Author: dblevins
Date: Wed May 19 23:46:40 2010
New Revision: 946485

URL: http://svn.apache.org/viewvc?rev=946485&view=rev
Log:
Patch from Andy Gumbrecht, OPENEJB-1266: Improved QuartzResourceAdapter
Thanks, Andy!

Modified:
    
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/resource/quartz/QuartzResourceAdapter.java

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/resource/quartz/QuartzResourceAdapter.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/resource/quartz/QuartzResourceAdapter.java?rev=946485&r1=946484&r2=946485&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/resource/quartz/QuartzResourceAdapter.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/resource/quartz/QuartzResourceAdapter.java
 Wed May 19 23:46:40 2010
@@ -17,7 +17,6 @@
 package org.apache.openejb.resource.quartz;
 
 import org.quartz.Scheduler;
-import org.quartz.SchedulerFactory;
 import org.quartz.SchedulerException;
 import org.quartz.Job;
 import org.quartz.JobDataMap;
@@ -33,45 +32,159 @@ import javax.resource.spi.endpoint.Messa
 import javax.resource.ResourceException;
 import javax.transaction.xa.XAResource;
 import java.lang.reflect.Method;
+import org.apache.openejb.util.LogCategory;
 
 /**
  * @version $Rev$ $Date$
-*/
+ */
 public class QuartzResourceAdapter implements 
javax.resource.spi.ResourceAdapter {
 
+    private static Exception ex = null;
     private Scheduler scheduler;
+    private BootstrapContext bootstrapContext;
+    private Thread startThread;
 
     public void start(BootstrapContext bootstrapContext) throws 
ResourceAdapterInternalException {
+
+        this.bootstrapContext = bootstrapContext;
+
+        startThread = new Thread("Quartz Scheduler Start") {
+
+            @Override
+            public void run() {
+
+                
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+
+                synchronized (QuartzResourceAdapter.this) {
+
+                    try {
+                        scheduler = StdSchedulerFactory.getDefaultScheduler();
+                    } catch (Exception e) {
+                        ex = e;
+                        return;
+                    }
+                }
+
+                try {
+                    scheduler.start();
+                } catch (Exception e) {
+                    ex = e;
+                }
+            }
+        };
+
+        startThread.setDaemon(true);
+        startThread.start();
+
         try {
-            SchedulerFactory factory = new StdSchedulerFactory();
-            scheduler = factory.getScheduler();
-            scheduler.start();
-        } catch (SchedulerException e) {
-            throw new ResourceAdapterInternalException("Failed to create 
Quartz Scheduler", e);
+            startThread.join(5000);
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+        }
+
+
+        if (null != ex) {
+            throw new ResourceAdapterInternalException("Failed to create 
Quartz Scheduler", ex);
         }
+
+        org.apache.openejb.util.Logger.getInstance(LogCategory.OPENEJB, 
"org.apache.openejb.util.resources").info("Started Quartz Scheduler");
+    }
+
+    public Scheduler getScheduler() {
+        return scheduler;
+    }
+
+    public BootstrapContext getBootstrapContext() {
+        return bootstrapContext;
     }
 
     public void stop() {
-        try {
-            scheduler.shutdown(true);
-        } catch (SchedulerException e) {
-            throw new IllegalStateException("Failed to shutdown Quartz 
Scheduler", e);
+
+        synchronized (this) {
+
+            if (null != scheduler) {
+
+                if (startThread.isAlive()) {
+                    startThread.interrupt();
+                }
+
+                Thread stopThread = new Thread("Quartz Scheduler Requested 
Stop") {
+
+                    @Override
+                    public void run() {
+                        try {
+                            scheduler.shutdown(true);
+                        } catch (Exception e) {
+                            ex = e;
+                        }
+                    }
+                };
+
+                stopThread.setDaemon(true);
+                stopThread.start();
+
+                try {
+                    //Block for a maximum of 5 seconds waiting for this thread 
to die.
+                    stopThread.join(5000);
+                } catch (InterruptedException ie) {
+                    //Ignore
+                }
+
+                try {
+                    if (!scheduler.isShutdown()) {
+
+                        stopThread = new Thread("Quartz Scheduler Forced 
Stop") {
+
+                            @Override
+                            public void run() {
+                                try {
+                                    //Try to force a shutdown
+                                    scheduler.shutdown(false);
+                                    
org.apache.openejb.util.Logger.getInstance(LogCategory.OPENEJB, 
"org.apache.openejb.util.resources").warning("Forced Quartz stop - Jobs may be 
incomplete");
+                                } catch (Exception e) {
+                                    ex = e;
+                                }
+                            }
+                        };
+
+                        stopThread.setDaemon(true);
+                        stopThread.start();
+                    }
+                } catch (Exception e) {
+                    ex = e;
+                }
+            }
+        }
+
+        this.bootstrapContext = null;
+
+        if (null != ex) {
+            org.apache.openejb.util.Logger.getInstance(LogCategory.OPENEJB, 
"org.apache.openejb.util.resources").warning("Error stopping Quartz Scheduler", 
ex);
+            return;
         }
+
+        org.apache.openejb.util.Logger.getInstance(LogCategory.OPENEJB, 
"org.apache.openejb.util.resources").info("Stopped Quartz Scheduler");
     }
 
     public void endpointActivation(MessageEndpointFactory 
messageEndpointFactory, ActivationSpec activationSpec) throws ResourceException 
{
-        JobSpec spec = (JobSpec) activationSpec;
 
-        MessageEndpoint endpoint = messageEndpointFactory.createEndpoint(null);
-        spec.setEndpoint(endpoint);
+        if (null == scheduler) {
+            throw new ResourceException("Quartz Scheduler is not available");
+        }
 
-        Job job = (Job) endpoint;
+        try {
 
-        JobDataMap jobDataMap = spec.getDetail().getJobDataMap();
-        jobDataMap.setAllowsTransientData(true);
-        jobDataMap.put(Data.class.getName(), new Data(job));
+            JobSpec spec = (JobSpec) activationSpec;
+
+            MessageEndpoint endpoint = 
messageEndpointFactory.createEndpoint(null);
+            spec.setEndpoint(endpoint);
+
+            Job job = (Job) endpoint;
+
+            JobDataMap jobDataMap = spec.getDetail().getJobDataMap();
+            jobDataMap.setAllowsTransientData(true);
+            jobDataMap.put(Data.class.getName(), new Data(job));
 
-        try {
             scheduler.scheduleJob(spec.getDetail(), spec.getTrigger());
         } catch (SchedulerException e) {
             throw new ResourceException("Failed to schedule job", e);
@@ -79,45 +192,66 @@ public class QuartzResourceAdapter imple
     }
 
     public void endpointDeactivation(MessageEndpointFactory 
messageEndpointFactory, ActivationSpec activationSpec) {
-        JobSpec spec = (JobSpec) activationSpec;
+
+        if (null == scheduler) {
+            throw new IllegalStateException("Quartz Scheduler is not 
available");
+        }
+
+        JobSpec spec = null;
 
         try {
+            spec = (JobSpec) activationSpec;
             scheduler.deleteJob(spec.getJobName(), spec.getJobGroup());
+
         } catch (SchedulerException e) {
             throw new IllegalStateException("Failed to delete job", e);
+        } finally {
+            if (null != spec) {
+                spec.getEndpoint().release();
+            }
         }
-
-        spec.getEndpoint().release();
     }
 
-
     public static class JobEndpoint implements Job {
 
+        private static Method method = null;
+
         public void execute(JobExecutionContext execution) throws 
JobExecutionException {
 
-            JobDataMap jobDataMap = execution.getJobDetail().getJobDataMap();
+            MessageEndpoint endpoint = null;
+
+            try {
 
-            Data data = Data.class.cast(jobDataMap.get(Data.class.getName()));
+                JobDataMap jobDataMap = 
execution.getJobDetail().getJobDataMap();
 
-            Job job = data.job;
+                Data data = 
Data.class.cast(jobDataMap.get(Data.class.getName()));
 
-            MessageEndpoint endpoint = (MessageEndpoint) job;
+                Job job = data.job;
 
-            try {
-                Method method = Job.class.getMethod("execute", 
JobExecutionContext.class);
+                endpoint = (MessageEndpoint) job;
+
+                if (null == method) {
+                    method = Job.class.getMethod("execute", 
JobExecutionContext.class);
+                }
 
                 endpoint.beforeDelivery(method);
 
                 job.execute(execution);
+
             } catch (NoSuchMethodException e) {
                 throw new IllegalStateException(e);
             } catch (ResourceException e) {
                 throw new JobExecutionException(e);
+            } catch (Throwable t) {
+                throw new JobExecutionException(new Exception(t));
             } finally {
-                try {
-                    endpoint.afterDelivery();
-                } catch (ResourceException e) {
-                    throw new JobExecutionException(e);
+
+                if (null != endpoint) {
+                    try {
+                        endpoint.afterDelivery();
+                    } catch (ResourceException e) {
+                        throw new JobExecutionException(e);
+                    }
                 }
             }
         }
@@ -129,6 +263,7 @@ public class QuartzResourceAdapter imple
      * outside code from becoming dependent on or tampering with the private 
data.
      */
     private static class Data {
+
         private final Job job;
 
         private Data(Job job) {


Reply via email to