You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by sa...@apache.org on 2012/08/07 08:26:13 UTC

svn commit: r1370126 [11/15] - in /ofbiz/branches/jackrabbit20120501: ./ applications/accounting/script/org/ofbiz/accounting/payment/ applications/accounting/src/org/ofbiz/accounting/payment/ applications/accounting/webapp/accounting/WEB-INF/ applicati...

Modified: ofbiz/branches/jackrabbit20120501/framework/service/src/org/ofbiz/service/job/JobManager.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20120501/framework/service/src/org/ofbiz/service/job/JobManager.java?rev=1370126&r1=1370125&r2=1370126&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20120501/framework/service/src/org/ofbiz/service/job/JobManager.java (original)
+++ ofbiz/branches/jackrabbit20120501/framework/service/src/org/ofbiz/service/job/JobManager.java Tue Aug  7 06:25:59 2012
@@ -23,12 +23,13 @@ import java.sql.Timestamp;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.RejectedExecutionException;
 
 import javolution.util.FastList;
-import javolution.util.FastMap;
 
+import org.ofbiz.base.util.Assert;
 import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.GeneralRuntimeException;
 import org.ofbiz.base.util.UtilDateTime;
 import org.ofbiz.base.util.UtilMisc;
 import org.ofbiz.base.util.UtilProperties;
@@ -45,63 +46,79 @@ import org.ofbiz.entity.serialize.XmlSer
 import org.ofbiz.entity.transaction.GenericTransactionException;
 import org.ofbiz.entity.transaction.TransactionUtil;
 import org.ofbiz.service.DispatchContext;
-import org.ofbiz.service.GenericDispatcher;
 import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.ServiceContainer;
 import org.ofbiz.service.calendar.RecurrenceInfo;
 import org.ofbiz.service.calendar.RecurrenceInfoException;
 import org.ofbiz.service.config.ServiceConfigUtil;
 
 /**
- * JobManager
+ * Job manager. The job manager queues jobs. It contains a <code>JobPoller</code> and a
+ * <code>Delegator</code>. Client code can queue a job to be run immediately by calling the
+ * {@link #runJob(Job)} method, or schedule a job to be run later by calling the
+ * {@link #schedule(String, String, String, Map, long, int, int, int, long, int)} method.
+ * Scheduled jobs are persisted in the JobSandbox entity.
  */
-public class JobManager {
+public final class JobManager {
 
+    public static final String module = JobManager.class.getName();
     public static final String instanceId = UtilProperties.getPropertyValue("general.properties", "unique.instanceId", "ofbiz0");
     public static final Map<String, Object> updateFields = UtilMisc.<String, Object>toMap("runByInstanceId", instanceId, "statusId", "SERVICE_QUEUED");
-    public static final String module = JobManager.class.getName();
-    public static Map<String, JobManager> registeredManagers = FastMap.newInstance();
-
-    protected Delegator delegator;
-    protected JobPoller jp;
-
-    /** Creates a new JobManager object. */
-    public JobManager(Delegator delegator) {
-        this(delegator, true);
-    }
+    private static final ConcurrentHashMap<String, JobManager> registeredManagers = new ConcurrentHashMap<String, JobManager>();
+    private static boolean isShutDown = false;
 
-    public JobManager(Delegator delegator, boolean enabled) {
-        if (delegator == null) {
-            throw new GeneralRuntimeException("ERROR: null delegator passed, cannot create JobManager");
-        }
-        if (JobManager.registeredManagers.get(delegator.getDelegatorName()) != null) {
-            throw new GeneralRuntimeException("JobManager for [" + delegator.getDelegatorName() + "] already running");
+    private static void assertIsRunning() {
+        if (isShutDown) {
+            throw new IllegalStateException("OFBiz shutting down");
         }
-
-        this.delegator = delegator;
-        jp = new JobPoller(this, enabled);
-        JobManager.registeredManagers.put(delegator.getDelegatorName(), this);
     }
 
-    public static JobManager getInstance(Delegator delegator, boolean enabled)
-    {
+    /**
+     * Returns a <code>JobManager</code> instance.
+     * @param delegator
+     * @param enablePoller Enables polling of the JobSandbox entity.
+     * @throws IllegalStateException if the Job Manager is shut down.
+     */
+    public static JobManager getInstance(Delegator delegator, boolean enablePoller) {
+        assertIsRunning();
+        Assert.notNull("delegator", delegator);
         JobManager jm = JobManager.registeredManagers.get(delegator.getDelegatorName());
         if (jm == null) {
-            jm = new JobManager(delegator, enabled);
+            jm = new JobManager(delegator);
+            JobManager.registeredManagers.putIfAbsent(delegator.getDelegatorName(), jm);
+            jm = JobManager.registeredManagers.get(delegator.getDelegatorName());
+            if (enablePoller) {
+                jm.enablePoller();
+            }
         }
         return jm;
     }
 
-    /** Queues a Job to run now. */
-    public void runJob(Job job) throws JobManagerException {
-        if (job.isValid()) {
-            jp.queueNow(job);
+    /**
+     * Shuts down all job managers. This method is called when OFBiz shuts down.
+     */
+    public static void shutDown() {
+        isShutDown = true;
+        for (JobManager jm : registeredManagers.values()) {
+            jm.shutdown();
         }
     }
 
-    /** Returns the ServiceDispatcher. */
-    public LocalDispatcher getDispatcher() {
-        LocalDispatcher thisDispatcher = GenericDispatcher.getLocalDispatcher(delegator.getDelegatorName(), delegator);
-        return thisDispatcher;
+    private final Delegator delegator;
+    private final JobPoller jp;
+    private boolean pollerEnabled = false;
+
+    private JobManager(Delegator delegator) {
+        this.delegator = delegator;
+        jp = new JobPoller(this);
+    }
+
+    private synchronized void enablePoller() {
+        if (!pollerEnabled) {
+            pollerEnabled = true;
+            reloadCrashedJobs();
+            jp.enable();
+        }
     }
 
     /** Returns the Delegator. */
@@ -109,123 +126,108 @@ public class JobManager {
         return this.delegator;
     }
 
-    public synchronized List<Job> poll() {
-        List<Job> poll = FastList.newInstance();
+    /** Returns the LocalDispatcher. */
+    public LocalDispatcher getDispatcher() {
+        LocalDispatcher thisDispatcher = ServiceContainer.getLocalDispatcher(delegator.getDelegatorName(), delegator);
+        return thisDispatcher;
+    }
+
+    /**
+     * Get a List of each threads current state.
+     * 
+     * @return List containing a Map of each thread's state.
+     */
+    public Map<String, Object> getPoolState() {
+        return jp.getPoolState();
+    }
 
+    /**
+     * Scans the JobSandbox entity and returns a list of jobs that are due to run.
+     * Returns an empty list if there are no jobs due to run.
+     * This method is called by the {@link JobPoller} polling thread.
+     */
+    protected synchronized List<Job> poll() {
+        assertIsRunning();
+        DispatchContext dctx = getDispatcher().getDispatchContext();
+        if (dctx == null) {
+            Debug.logError("Unable to locate DispatchContext object; not running job!", module);
+            return null;
+        }
+        List<Job> poll = FastList.newInstance();
         // sort the results by time
         List<String> order = UtilMisc.toList("runTime");
-
         // basic query
-        List<EntityExpr> expressions = UtilMisc.toList(EntityCondition.makeCondition("runTime", EntityOperator.LESS_THAN_EQUAL_TO,
-                UtilDateTime.nowTimestamp()), EntityCondition.makeCondition("startDateTime", EntityOperator.EQUALS, null),
+        List<EntityExpr> expressions = UtilMisc.toList(EntityCondition.makeCondition("runTime", EntityOperator.LESS_THAN_EQUAL_TO, UtilDateTime.nowTimestamp()),
+                EntityCondition.makeCondition("startDateTime", EntityOperator.EQUALS, null),
                 EntityCondition.makeCondition("cancelDateTime", EntityOperator.EQUALS, null),
                 EntityCondition.makeCondition("runByInstanceId", EntityOperator.EQUALS, null));
-
         // limit to just defined pools
         List<String> pools = ServiceConfigUtil.getRunPools();
         List<EntityExpr> poolsExpr = UtilMisc.toList(EntityCondition.makeCondition("poolId", EntityOperator.EQUALS, null));
         if (pools != null) {
-            for (String poolName: pools) {
+            for (String poolName : pools) {
                 poolsExpr.add(EntityCondition.makeCondition("poolId", EntityOperator.EQUALS, poolName));
             }
         }
-
         // make the conditions
         EntityCondition baseCondition = EntityCondition.makeCondition(expressions);
         EntityCondition poolCondition = EntityCondition.makeCondition(poolsExpr, EntityOperator.OR);
         EntityCondition mainCondition = EntityCondition.makeCondition(UtilMisc.toList(baseCondition, poolCondition));
-
-        // we will loop until we have no more to do
-        boolean pollDone = false;
-
-        while (!pollDone) {
-            // an extra protection for synchronization, help make sure we don't get in here more than once
-            synchronized (this) {
-                boolean beganTransaction = false;
-
-                try {
-                    beganTransaction = TransactionUtil.begin();
-                    if (!beganTransaction) {
-                        Debug.logError("Unable to poll for jobs; transaction was not started by this process", module);
-                        return null;
-                    }
-
-                    List<Job> localPoll = FastList.newInstance();
-
-                    // first update the jobs w/ this instance running information
-                    delegator.storeByCondition("JobSandbox", updateFields, mainCondition);
-
-                    // now query all the 'queued' jobs for this instance
-                    List<GenericValue> jobEnt = delegator.findByAnd("JobSandbox", updateFields, order, false);
-                    //jobEnt = delegator.findByCondition("JobSandbox", mainCondition, null, order);
-
-                    if (UtilValidate.isNotEmpty(jobEnt)) {
-                        for (GenericValue v: jobEnt) {
-                            DispatchContext dctx = getDispatcher().getDispatchContext();
-                            if (dctx == null) {
-                                Debug.logError("Unable to locate DispatchContext object; not running job!", module);
-                                continue;
-                            }
-                            Job job = new PersistedServiceJob(dctx, v, null); // TODO fix the requester
-                            try {
-                                job.queue();
-                                localPoll.add(job);
-                            } catch (InvalidJobException e) {
-                                Debug.logError(e, module);
-                            }
-                        }
-                    } else {
-                        pollDone = true;
-                    }
-
-                    // nothing should go wrong at this point, so add to the general list
-                    poll.addAll(localPoll);
-                } catch (Throwable t) {
-                    // catch Throwable so nothing slips through the cracks... this is a fairly sensitive operation
-                    String errMsg = "Error in polling JobSandbox: [" + t.toString() + "]. Rolling back transaction.";
-                    Debug.logError(t, errMsg, module);
-                    try {
-                        // only rollback the transaction if we started one...
-                        TransactionUtil.rollback(beganTransaction, errMsg, t);
-                    } catch (GenericEntityException e2) {
-                        Debug.logError(e2, "[Delegator] Could not rollback transaction: " + e2.toString(), module);
-                    }
-                } finally {
-                    try {
-                        // only commit the transaction if we started one... but make sure we try
-                        TransactionUtil.commit(beganTransaction);
-                    } catch (GenericTransactionException e) {
-                        String errMsg = "Transaction error trying to commit when polling and updating the JobSandbox: " + e.toString();
-                        // we don't really want to do anything different, so just log and move on
-                        Debug.logError(e, errMsg, module);
-                    }
+        boolean beganTransaction = false;
+        try {
+            beganTransaction = TransactionUtil.begin();
+            if (!beganTransaction) {
+                Debug.logError("Unable to poll for jobs; transaction was not started by this process", module);
+                return null;
+            }
+            // first update the jobs w/ this instance running information
+            delegator.storeByCondition("JobSandbox", updateFields, mainCondition);
+            // now query all the 'queued' jobs for this instance
+            List<GenericValue> jobEnt = delegator.findByAnd("JobSandbox", updateFields, order, false);
+            if (UtilValidate.isNotEmpty(jobEnt)) {
+                for (GenericValue v : jobEnt) {
+                    poll.add(new PersistedServiceJob(dctx, v, null)); // TODO fix the requester
                 }
             }
+        } catch (Throwable t) {
+            // catch Throwable so nothing slips through the cracks... this is a fairly sensitive operation
+            String errMsg = "Error in polling JobSandbox: [" + t.toString() + "]. Rolling back transaction.";
+            Debug.logError(t, errMsg, module);
+            try {
+                // only rollback the transaction if we started one...
+                TransactionUtil.rollback(beganTransaction, errMsg, t);
+            } catch (GenericEntityException e2) {
+                Debug.logError(e2, "[Delegator] Could not rollback transaction: " + e2.toString(), module);
+            }
+        } finally {
+            try {
+                // only commit the transaction if we started one... but make sure we try
+                TransactionUtil.commit(beganTransaction);
+            } catch (GenericTransactionException e) {
+                String errMsg = "Transaction error trying to commit when polling and updating the JobSandbox: " + e.toString();
+                // we don't really want to do anything different, so just log and move on
+                Debug.logError(e, errMsg, module);
+            }
         }
         return poll;
     }
 
-    public synchronized void reloadCrashedJobs() {
-        String instanceId = UtilProperties.getPropertyValue("general.properties", "unique.instanceId", "ofbiz0");
+    private void reloadCrashedJobs() {
         List<GenericValue> crashed = null;
-
         List<EntityExpr> exprs = UtilMisc.toList(EntityCondition.makeCondition("runByInstanceId", instanceId));
         exprs.add(EntityCondition.makeCondition("statusId", EntityOperator.EQUALS, "SERVICE_RUNNING"));
         EntityConditionList<EntityExpr> ecl = EntityCondition.makeCondition(exprs);
-
         try {
             crashed = delegator.findList("JobSandbox", ecl, null, UtilMisc.toList("startDateTime"), null, false);
         } catch (GenericEntityException e) {
             Debug.logError(e, "Unable to load crashed jobs", module);
         }
-
         if (UtilValidate.isNotEmpty(crashed)) {
             try {
                 int rescheduled = 0;
-                for (GenericValue job: crashed) {
+                for (GenericValue job : crashed) {
                     Timestamp now = UtilDateTime.nowTimestamp();
-                    Debug.log("Scheduling Job : " + job, module);
-
+                    Debug.logInfo("Scheduling Job : " + job, module);
                     String pJobId = job.getString("parentJobId");
                     if (pJobId == null) {
                         pJobId = job.getString("jobId");
@@ -238,33 +240,49 @@ public class JobManager {
                     newJob.set("startDateTime", null);
                     newJob.set("runByInstanceId", null);
                     delegator.createSetNextSeqId(newJob);
-
                     // set the cancel time on the old job to the same as the re-schedule time
                     job.set("statusId", "SERVICE_CRASHED");
                     job.set("cancelDateTime", now);
                     delegator.store(job);
-
                     rescheduled++;
                 }
-
-                if (Debug.infoOn()) Debug.logInfo("-- " + rescheduled + " jobs re-scheduled", module);
+                if (Debug.infoOn())
+                    Debug.logInfo("-- " + rescheduled + " jobs re-scheduled", module);
             } catch (GenericEntityException e) {
                 Debug.logError(e, module);
             }
-
         } else {
-            if (Debug.infoOn()) Debug.logInfo("No crashed jobs to re-schedule", module);
+            if (Debug.infoOn())
+                Debug.logInfo("No crashed jobs to re-schedule", module);
+        }
+    }
+
+    /** Queues a Job to run now.
+     * @throws IllegalStateException if the Job Manager is shut down.
+     * @throws RejectedExecutionException if the poller is stopped.
+     */
+    public void runJob(Job job) throws JobManagerException {
+        assertIsRunning();
+        if (job.isValid()) {
+            jp.queueNow(job);
         }
     }
 
     /**
      * Schedule a job to start at a specific time with specific recurrence info
-     *@param serviceName The name of the service to invoke
-     *@param context The context for the service
-     *@param startTime The time in milliseconds the service should run
-     *@param frequency The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc)
-     *@param interval The interval of the frequency recurrence
-     *@param count The number of times to repeat
+     * 
+     * @param serviceName
+     *            The name of the service to invoke
+     *@param context
+     *            The context for the service
+     *@param startTime
+     *            The time in milliseconds the service should run
+     *@param frequency
+     *            The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc)
+     *@param interval
+     *            The interval of the frequency recurrence
+     *@param count
+     *            The number of times to repeat
      */
     public void schedule(String serviceName, Map<String, ? extends Object> context, long startTime, int frequency, int interval, int count) throws JobManagerException {
         schedule(serviceName, context, startTime, frequency, interval, count, 0);
@@ -272,65 +290,113 @@ public class JobManager {
 
     /**
      * Schedule a job to start at a specific time with specific recurrence info
-     *@param serviceName The name of the service to invoke
-     *@param context The context for the service
-     *@param startTime The time in milliseconds the service should run
-     *@param frequency The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc)
-     *@param interval The interval of the frequency recurrence
-     *@param endTime The time in milliseconds the service should expire
+     * 
+     * @param serviceName
+     *            The name of the service to invoke
+     *@param context
+     *            The context for the service
+     *@param startTime
+     *            The time in milliseconds the service should run
+     *@param frequency
+     *            The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc)
+     *@param interval
+     *            The interval of the frequency recurrence
+     *@param count
+     *            The number of times to repeat
+     *@param endTime
+     *            The time in milliseconds the service should expire
      */
-    public void schedule(String serviceName, Map<String, ? extends Object> context, long startTime, int frequency, int interval, long endTime) throws JobManagerException {
-        schedule(serviceName, context, startTime, frequency, interval, -1, endTime);
+    public void schedule(String serviceName, Map<String, ? extends Object> context, long startTime, int frequency, int interval, int count, long endTime) throws JobManagerException {
+        schedule(null, serviceName, context, startTime, frequency, interval, count, endTime);
     }
 
     /**
      * Schedule a job to start at a specific time with specific recurrence info
-     *@param serviceName The name of the service to invoke
-     *@param context The context for the service
-     *@param startTime The time in milliseconds the service should run
-     *@param frequency The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc)
-     *@param interval The interval of the frequency recurrence
-     *@param count The number of times to repeat
-     *@param endTime The time in milliseconds the service should expire
+     * 
+     * @param serviceName
+     *            The name of the service to invoke
+     *@param context
+     *            The context for the service
+     *@param startTime
+     *            The time in milliseconds the service should run
+     *@param frequency
+     *            The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc)
+     *@param interval
+     *            The interval of the frequency recurrence
+     *@param endTime
+     *            The time in milliseconds the service should expire
      */
-    public void schedule(String serviceName, Map<String, ? extends Object> context, long startTime, int frequency, int interval, int count, long endTime) throws JobManagerException {
-        schedule(null, serviceName, context, startTime, frequency, interval, count, endTime);
+    public void schedule(String serviceName, Map<String, ? extends Object> context, long startTime, int frequency, int interval, long endTime) throws JobManagerException {
+        schedule(serviceName, context, startTime, frequency, interval, -1, endTime);
     }
 
     /**
      * Schedule a job to start at a specific time with specific recurrence info
-     *@param poolName The name of the pool to run the service from
-     *@param serviceName The name of the service to invoke
-     *@param context The context for the service
-     *@param startTime The time in milliseconds the service should run
-     *@param frequency The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc)
-     *@param interval The interval of the frequency recurrence
-     *@param count The number of times to repeat
-     *@param endTime The time in milliseconds the service should expire
+     * 
+     * @param poolName
+     *            The name of the pool to run the service from
+     *@param serviceName
+     *            The name of the service to invoke
+     *@param context
+     *            The context for the service
+     *@param startTime
+     *            The time in milliseconds the service should run
+     *@param frequency
+     *            The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc)
+     *@param interval
+     *            The interval of the frequency recurrence
+     *@param count
+     *            The number of times to repeat
+     *@param endTime
+     *            The time in milliseconds the service should expire
      */
-    public void schedule(String poolName, String serviceName, Map<String, ? extends Object> context, long startTime, int frequency, int interval, int count, long endTime) throws JobManagerException {
+    public void schedule(String poolName, String serviceName, Map<String, ? extends Object> context, long startTime, int frequency,
+            int interval, int count, long endTime) throws JobManagerException {
         schedule(null, null, serviceName, context, startTime, frequency, interval, count, endTime, -1);
     }
 
     /**
      * Schedule a job to start at a specific time with specific recurrence info
-     *@param jobName The name of the job
-     *@param poolName The name of the pool to run the service from
-     *@param serviceName The name of the service to invoke
-     *@param context The context for the service
-     *@param startTime The time in milliseconds the service should run
-     *@param frequency The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc)
-     *@param interval The interval of the frequency recurrence
-     *@param count The number of times to repeat
-     *@param endTime The time in milliseconds the service should expire
-     *@param maxRetry The max number of retries on failure (-1 for no max)
-     */
-    public void schedule(String jobName, String poolName, String serviceName, Map<String, ? extends Object> context, long startTime, int frequency, int interval, int count, long endTime, int maxRetry) throws JobManagerException {
-        if (delegator == null) {
-            Debug.logWarning("No delegator referenced; cannot schedule job.", module);
-            return;
-        }
+     * 
+     * @param poolName
+     *            The name of the pool to run the service from
+     *@param serviceName
+     *            The name of the service to invoke
+     *@param dataId
+     *            The persisted context (RuntimeData.runtimeDataId)
+     *@param startTime
+     *            The time in milliseconds the service should run
+     */
+    public void schedule(String poolName, String serviceName, String dataId, long startTime) throws JobManagerException {
+        schedule(null, poolName, serviceName, dataId, startTime, -1, 0, 1, 0, -1);
+    }
 
+    /**
+     * Schedule a job to start at a specific time with specific recurrence info
+     * 
+     * @param jobName
+     *            The name of the job
+     *@param poolName
+     *            The name of the pool to run the service from
+     *@param serviceName
+     *            The name of the service to invoke
+     *@param context
+     *            The context for the service
+     *@param startTime
+     *            The time in milliseconds the service should run
+     *@param frequency
+     *            The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc)
+     *@param interval
+     *            The interval of the frequency recurrence
+     *@param count
+     *            The number of times to repeat
+     *@param endTime
+     *            The time in milliseconds the service should expire
+     *@param maxRetry
+     *            The max number of retries on failure (-1 for no max)
+     */
+    public void schedule(String jobName, String poolName, String serviceName, Map<String, ? extends Object> context, long startTime,
+            int frequency, int interval, int count, long endTime, int maxRetry) throws JobManagerException {
         // persist the context
         String dataId = null;
         try {
@@ -345,41 +411,38 @@ public class JobManager {
         } catch (IOException ioe) {
             throw new JobManagerException(ioe.getMessage(), ioe);
         }
-
         // schedule the job
         schedule(jobName, poolName, serviceName, dataId, startTime, frequency, interval, count, endTime, maxRetry);
     }
 
     /**
      * Schedule a job to start at a specific time with specific recurrence info
-     *@param poolName The name of the pool to run the service from
-     *@param serviceName The name of the service to invoke
-     *@param dataId The persisted context (RuntimeData.runtimeDataId)
-     *@param startTime The time in milliseconds the service should run
+     * 
+     * @param jobName
+     *            The name of the job
+     *@param poolName
+     *            The name of the pool to run the service from
+     *@param serviceName
+     *            The name of the service to invoke
+     *@param dataId
+     *            The persisted context (RuntimeData.runtimeDataId)
+     *@param startTime
+     *            The time in milliseconds the service should run
+     *@param frequency
+     *            The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc)
+     *@param interval
+     *            The interval of the frequency recurrence
+     *@param count
+     *            The number of times to repeat
+     *@param endTime
+     *            The time in milliseconds the service should expire
+     *@param maxRetry
+     *            The max number of retries on failure (-1 for no max)
+     * @throws IllegalStateException if the Job Manager is shut down.
      */
-    public void schedule(String poolName, String serviceName, String dataId, long startTime) throws JobManagerException {
-        schedule(null, poolName, serviceName, dataId, startTime, -1, 0, 1, 0, -1);
-    }
-
-    /**
-     * Schedule a job to start at a specific time with specific recurrence info
-     *@param jobName The name of the job
-     *@param poolName The name of the pool to run the service from
-     *@param serviceName The name of the service to invoke
-     *@param dataId The persisted context (RuntimeData.runtimeDataId)
-     *@param startTime The time in milliseconds the service should run
-     *@param frequency The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc)
-     *@param interval The interval of the frequency recurrence
-     *@param count The number of times to repeat
-     *@param endTime The time in milliseconds the service should expire
-     *@param maxRetry The max number of retries on failure (-1 for no max)
-     */
-    public void schedule(String jobName, String poolName, String serviceName, String dataId, long startTime, int frequency, int interval, int count, long endTime, int maxRetry) throws JobManagerException {
-        if (delegator == null) {
-            Debug.logWarning("No delegator referenced; cannot schedule job.", module);
-            return;
-        }
-
+    public void schedule(String jobName, String poolName, String serviceName, String dataId, long startTime, int frequency, int interval,
+            int count, long endTime, int maxRetry) throws JobManagerException {
+        assertIsRunning();
         // create the recurrence
         String infoId = null;
         if (frequency > -1 && count != 0) {
@@ -390,28 +453,23 @@ public class JobManager {
                 throw new JobManagerException(e.getMessage(), e);
             }
         }
-
         // set the persisted fields
         if (UtilValidate.isEmpty(jobName)) {
             jobName = Long.toString((new Date().getTime()));
         }
-        Map<String, Object> jFields = UtilMisc.<String, Object>toMap("jobName", jobName, "runTime", new java.sql.Timestamp(startTime),
+        Map<String, Object> jFields = UtilMisc.<String, Object> toMap("jobName", jobName, "runTime", new java.sql.Timestamp(startTime),
                 "serviceName", serviceName, "statusId", "SERVICE_PENDING", "recurrenceInfoId", infoId, "runtimeDataId", dataId);
-
         // set the pool ID
         if (UtilValidate.isNotEmpty(poolName)) {
             jFields.put("poolId", poolName);
         } else {
             jFields.put("poolId", ServiceConfigUtil.getSendPool());
         }
-
         // set the loader name
         jFields.put("loaderName", delegator.getDelegatorName());
-
         // set the max retry
         jFields.put("maxRetry", Long.valueOf(maxRetry));
         jFields.put("currentRetryCount", new Long(0));
-
         // create the value and store
         GenericValue jobV;
         try {
@@ -422,63 +480,12 @@ public class JobManager {
         }
     }
 
-    /**
-     * Kill a JobInvoker Thread.
-     * @param threadName Name of the JobInvoker Thread to kill.
-     */
-    public void killThread(String threadName) {
-        jp.killThread(threadName);
-    }
-
-    /**
-     * Get a List of each threads current state.
-     * @return List containing a Map of each thread's state.
-     */
-    public List<Map<String, Object>> processList() {
-        return jp.getPoolState();
-    }
-
     /** Close out the scheduler thread. */
     public void shutdown() {
-        if (jp != null) {
-            jp.stop();
-            jp = null;
-            Debug.logInfo("JobManager: Stopped Scheduler Thread.", module);
-        }
-    }
-
-    @Override
-    public void finalize() throws Throwable {
-        this.shutdown();
-        super.finalize();
-    }
-
-    /** gets the recurrence info object for a job. */
-    public static RecurrenceInfo getRecurrenceInfo(GenericValue job) {
-        try {
-            if (job != null && !UtilValidate.isEmpty(job.getString("recurrenceInfoId"))) {
-                if (job.get("cancelDateTime") != null) {
-                    // cancel has been flagged, no more recurrence
-                    return null;
-                }
-                GenericValue ri = job.getRelatedOne("RecurrenceInfo", false);
-
-                if (ri != null) {
-                    return new RecurrenceInfo(ri);
-                } else {
-                    return null;
-                }
-            } else {
-                return null;
-            }
-        } catch (GenericEntityException e) {
-            e.printStackTrace();
-            Debug.logError(e, "Problem getting RecurrenceInfo entity from JobSandbox", module);
-        } catch (RecurrenceInfoException re) {
-            re.printStackTrace();
-            Debug.logError(re, "Problem creating RecurrenceInfo instance: " + re.getMessage(), module);
-        }
-        return null;
+        Debug.logInfo("Stopping the JobManager...", module);
+        registeredManagers.remove(delegator.getDelegatorName(), this);
+        jp.stop();
+        Debug.logInfo("JobManager stopped.", module);
     }
 
 }

Modified: ofbiz/branches/jackrabbit20120501/framework/service/src/org/ofbiz/service/job/JobPoller.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20120501/framework/service/src/org/ofbiz/service/job/JobPoller.java?rev=1370126&r1=1370125&r2=1370126&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20120501/framework/service/src/org/ofbiz/service/job/JobPoller.java (original)
+++ ofbiz/branches/jackrabbit20120501/framework/service/src/org/ofbiz/service/job/JobPoller.java Tue Aug  7 06:25:59 2012
@@ -18,93 +18,64 @@
  *******************************************************************************/
 package org.ofbiz.service.job;
 
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-
-import javolution.util.FastList;
-import javolution.util.FastMap;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
 
 import org.ofbiz.base.util.Debug;
 import org.ofbiz.service.config.ServiceConfigUtil;
 
+import org.apache.commons.lang.math.NumberUtils;
+
 /**
- * JobPoller - Polls for persisted jobs to run.
+ * Job poller. Queues and runs jobs.
  */
-public class JobPoller implements Runnable {
+public final class JobPoller implements Runnable {
 
     public static final String module = JobPoller.class.getName();
-
     public static final int MIN_THREADS = 1;
     public static final int MAX_THREADS = 15;
-    public static final int MAX_JOBS = 3;
     public static final int POLL_WAIT = 20000;
-    //public static final long MAX_TTL = 18000000;
+    public static final long THREAD_TTL = 18000000;
 
-    protected Thread thread = null;
-    protected List<JobInvoker> pool = null;
-    protected List<Job> run = null;
-    protected JobManager jm = null;
-
-    protected volatile boolean isRunning = false;
+    private final JobManager jm;
+    private final ThreadPoolExecutor executor;
+    private final String name;
+    private boolean enabled = false;
 
     /**
      * Creates a new JobScheduler
-     * @param jm JobManager associated with this scheduler
+     * 
+     * @param jm
+     *            JobManager associated with this scheduler
      */
-    public JobPoller(JobManager jm, boolean enabled) {
+    public JobPoller(JobManager jm) {
+        this.name = jm.getDelegator().getDelegatorName();
         this.jm = jm;
-        this.run = FastList.newInstance();
-
-        // create the thread pool
-        this.pool = createThreadPool();
-
-        if (enabled) {
-            // re-load crashed jobs
-            this.jm.reloadCrashedJobs();
+        this.executor = new ThreadPoolExecutor(minThreads(), maxThreads(), getTTL(), TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(),
+                new JobInvokerThreadFactory(this.name), new ThreadPoolExecutor.AbortPolicy());
+    }
 
+    public synchronized void enable() {
+        if (!enabled) {
+            enabled = true;
             // start the thread only if polling is enabled
             if (pollEnabled()) {
-
                 // create the poller thread
-                thread = new Thread(this, this.toString());
+                Thread thread = new Thread(this, "OFBiz-JobPoller-" + this.name);
                 thread.setDaemon(false);
-
                 // start the poller
-                this.isRunning = true;
                 thread.start();
             }
         }
     }
 
-    protected JobPoller() {}
-
-    public synchronized void run() {
-        try {
-            // wait 30 seconds before the first poll
-            java.lang.Thread.sleep(30000);
-        } catch (InterruptedException e) {
-        }
-        while (isRunning) {
-            try {
-                // grab a list of jobs to run.
-                List<Job> pollList = jm.poll();
-                //Debug.logInfo("Received poll list from JobManager [" + pollList.size() + "]", module);
-
-                for (Job job : pollList) {
-                    if (job.isValid()) {
-                        queueNow(job);
-                        //Debug.logInfo("Job [" + job.getJobId() + "] is queued", module);
-                    }
-                }
-                // NOTE: using sleep instead of wait for stricter locking
-                java.lang.Thread.sleep(pollWaitTime());
-            } catch (InterruptedException e) {
-                Debug.logError(e, module);
-                stop();
-            }
-        }
-    }
-
     /**
      * Returns the JobManager
      */
@@ -112,139 +83,47 @@ public class JobPoller implements Runnab
         return jm;
     }
 
-    /**
-     * Stops the JobPoller
-     */
-    public void stop() {
-        isRunning = false;
-        destroyThreadPool();
-    }
-
-    public List<Map<String, Object>> getPoolState() {
-        List<Map<String, Object>> stateList = FastList.newInstance();
-        for (JobInvoker invoker: this.pool) {
-            Map<String, Object> stateMap = FastMap.newInstance();
-            stateMap.put("threadName", invoker.getName());
-            stateMap.put("threadId", invoker.getThreadId());
-            stateMap.put("jobName", invoker.getJobName());
-            stateMap.put("serviceName", invoker.getServiceName());
-            stateMap.put("usage", invoker.getUsage());
-            stateMap.put("ttl", invoker.getTimeRemaining());
-            stateMap.put("runTime", invoker.getCurrentRuntime());
-            stateMap.put("status", invoker.getCurrentStatus());
-            stateList.add(stateMap);
-        }
-        return stateList;
-    }
-
-    /**
-     * Stops all threads in the threadPool and clears
-     * the pool as final step.
-     */
-    private void destroyThreadPool() {
-        Debug.logInfo("Destroying thread pool...", module);
-        for (JobInvoker ji: pool) {
-            ji.stop();
-        }
-        pool.clear();
-    }
-
-    public synchronized void killThread(String threadName) {
-        JobInvoker inv = findThread(threadName);
-        if (inv != null) {
-            inv.kill();
-            this.pool.remove(inv);
-        }
-    }
-
-    private JobInvoker findThread(String threadName) {
-        for (JobInvoker inv: pool) {
-            if (threadName.equals(inv.getName())) {
-                return inv;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Returns the next job to run
-     */
-    public Job next() {
-        if (run.size() > 0) {
-            // NOTE: this syncrhonized isn't really necessary as the only method that calls it is already synchronized (the JobInvoker.run method), so this is here as an added protection especially for the case where it might be used differently in the future
-            synchronized (run) {
-                // make sure the size is still greater than zero
-                if (run.size() > 0) {
-                    return run.remove(0);
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Adds a job to the RUN queue
-     */
-    public void queueNow(Job job) {
-        //Debug.logInfo("[" + Thread.currentThread().getId() + "] Begin queueNow; holds run lock? " + Thread.holdsLock(run), module);
-
-        // NOTE DEJ20071201 MUST use a different object for the lock here because the "this" object is always held by the poller thread in the run method above (which sleeps and runs)
-        synchronized (run) {
-            run.add(job);
-        }
-        if (Debug.verboseOn()) Debug.logVerbose("New run queue size: " + run.size(), module);
-        if (run.size() > pool.size() && pool.size() < maxThreads()) {
-            synchronized (pool) {
-                if (run.size() > pool.size() && pool.size() < maxThreads()) {
-                    int calcSize = (run.size() / jobsPerThread()) - (pool.size());
-                    int addSize = calcSize > maxThreads() ? maxThreads() : calcSize;
-
-                    for (int i = 0; i < addSize; i++) {
-                        JobInvoker iv = new JobInvoker(this, invokerWaitTime());
-                        pool.add(iv);
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Removes a thread from the pool.
-     * @param invoker The invoker to remove.
-     */
-    public void removeThread(JobInvoker invoker) {
-        if (pool != null) {
-            synchronized (pool) {
-                pool.remove(invoker);
-                invoker.stop();
-            }
-        }
-
-        if (pool != null && pool.size() < minThreads()) {
-            synchronized (pool) {
-                for (int i = 0; i < minThreads() - pool.size(); i++) {
-                    JobInvoker iv = new JobInvoker(this, invokerWaitTime());
-                    pool.add(iv);
-                }
-            }
+    public Map<String, Object> getPoolState() {
+        Map<String, Object> poolState = new HashMap<String, Object>();
+        poolState.put("pollerName", this.name);
+        poolState.put("pollerThreadName", "OFBiz-JobPoller-" + this.name);
+        poolState.put("invokerThreadNameFormat", "OFBiz-JobInvoker-" + this.name + "-<SEQ>");
+        poolState.put("keepAliveTimeInSeconds", this.executor.getKeepAliveTime(TimeUnit.SECONDS));
+        poolState.put("numberOfCoreInvokerThreads", this.executor.getCorePoolSize());
+        poolState.put("currentNumberOfInvokerThreads", this.executor.getPoolSize());
+        poolState.put("numberOfActiveInvokerThreads", this.executor.getActiveCount());
+        poolState.put("maxNumberOfInvokerThreads", this.executor.getMaximumPoolSize());
+        poolState.put("greatestNumberOfInvokerThreads", this.executor.getLargestPoolSize());
+        poolState.put("numberOfCompletedTasks", this.executor.getCompletedTaskCount());
+        BlockingQueue<Runnable> queue = this.executor.getQueue();
+        List<Map<String, Object>> taskList = new ArrayList<Map<String, Object>>();
+        Map<String, Object> taskInfo = null;
+        for (Runnable task : queue) {
+            JobInvoker jobInvoker = (JobInvoker) task;
+            taskInfo = new HashMap<String, Object>();
+            taskInfo.put("id", jobInvoker.getJobId());
+            taskInfo.put("name", jobInvoker.getJobName());
+            taskInfo.put("serviceName", jobInvoker.getServiceName());
+            taskInfo.put("time", jobInvoker.getTime());
+            taskInfo.put("runtime", jobInvoker.getCurrentRuntime());
+            taskList.add(taskInfo);
         }
+        poolState.put("taskList", taskList);
+        return poolState;
     }
 
-    // Creates the invoker pool
-    private List<JobInvoker> createThreadPool() {
-        List<JobInvoker> threadPool = FastList.newInstance();
-
-        while (threadPool.size() < minThreads()) {
-            JobInvoker iv = new JobInvoker(this, invokerWaitTime());
-            threadPool.add(iv);
+    private long getTTL() {
+        long ttl = THREAD_TTL;
+        try {
+            ttl = NumberUtils.toLong(ServiceConfigUtil.getElementAttr("thread-pool", "ttl"));
+        } catch (NumberFormatException nfe) {
+            Debug.logError("Problems reading value from attribute [ttl] of element [thread-pool] in serviceengine.xml file [" + nfe.toString() + "]. Using default (" + THREAD_TTL + ").", module);
         }
-
-        return threadPool;
+        return ttl;
     }
 
     private int maxThreads() {
         int max = MAX_THREADS;
-
         try {
             max = Integer.parseInt(ServiceConfigUtil.getElementAttr("thread-pool", "max-threads"));
         } catch (NumberFormatException nfe) {
@@ -255,7 +134,6 @@ public class JobPoller implements Runnab
 
     private int minThreads() {
         int min = MIN_THREADS;
-
         try {
             min = Integer.parseInt(ServiceConfigUtil.getElementAttr("thread-pool", "min-threads"));
         } catch (NumberFormatException nfe) {
@@ -264,31 +142,15 @@ public class JobPoller implements Runnab
         return min;
     }
 
-    private int jobsPerThread() {
-        int jobs = MAX_JOBS;
-
-        try {
-            jobs = Integer.parseInt(ServiceConfigUtil.getElementAttr("thread-pool", "jobs"));
-        } catch (NumberFormatException nfe) {
-            Debug.logError("Problems reading values from serviceengine.xml file [" + nfe.toString() + "]. Using defaults.", module);
-        }
-        return jobs;
-    }
-
-    private int invokerWaitTime() {
-        int wait = JobInvoker.WAIT_TIME;
-
-        try {
-            wait = Integer.parseInt(ServiceConfigUtil.getElementAttr("thread-pool", "wait-millis"));
-        } catch (NumberFormatException nfe) {
-            Debug.logError("Problems reading values from serviceengine.xml file [" + nfe.toString() + "]. Using defaults.", module);
-        }
-        return wait;
+    private boolean pollEnabled() {
+        String enabled = ServiceConfigUtil.getElementAttr("thread-pool", "poll-enabled");
+        if (enabled.equalsIgnoreCase("false"))
+            return false;
+        return true;
     }
 
     private int pollWaitTime() {
         int poll = POLL_WAIT;
-
         try {
             poll = Integer.parseInt(ServiceConfigUtil.getElementAttr("thread-pool", "poll-db-millis"));
         } catch (NumberFormatException nfe) {
@@ -297,19 +159,66 @@ public class JobPoller implements Runnab
         return poll;
     }
 
-    private boolean pollEnabled() {
-        String enabled = ServiceConfigUtil.getElementAttr("thread-pool", "poll-enabled");
-
-        if (enabled.equalsIgnoreCase("false"))
-            return false;
+    /**
+     * Adds a job to the RUN queue.
+     * @throws InvalidJobException if the job is in an invalid state.
+     * @throws RejectedExecutionException if the poller is stopped.
+     */
+    public void queueNow(Job job) throws InvalidJobException {
+        job.queue();
+        this.executor.execute(new JobInvoker(job));
+    }
 
-        // also make sure we have a delegator to use for polling
-        if (jm.getDelegator() == null) {
-            Debug.logWarning("No delegator referenced; not starting job poller.", module);
-            return false;
+    public synchronized void run() {
+        try {
+            // wait 30 seconds before the first poll
+            java.lang.Thread.sleep(30000);
+        } catch (InterruptedException e) {
         }
+        while (!executor.isShutdown()) {
+            try {
+                // grab a list of jobs to run.
+                List<Job> pollList = jm.poll();
+                for (Job job : pollList) {
+                    try {
+                        queueNow(job);
+                    } catch (InvalidJobException e) {
+                        Debug.logError(e, module);
+                    }
+                }
+                // NOTE: using sleep instead of wait for stricter locking
+                java.lang.Thread.sleep(pollWaitTime());
+            } catch (InterruptedException e) {
+                Debug.logError(e, module);
+                stop();
+            }
+        }
+        Debug.logInfo("JobPoller " + this.name + " thread terminated.", module);
+    }
 
-        return true;
+    /**
+     * Stops the JobPoller
+     */
+    void stop() {
+        Debug.logInfo("Shutting down thread pool for JobPoller " + this.name, module);
+        this.executor.shutdown();
+        try {
+            // Wait 60 seconds for existing tasks to terminate
+            if (!this.executor.awaitTermination(60, TimeUnit.SECONDS)) {
+                // abrupt shutdown (cancel currently executing tasks)
+                Debug.logInfo("Attempting abrupt shut down of thread pool for JobPoller " + this.name, module);
+                this.executor.shutdownNow();
+                // Wait 60 seconds for tasks to respond to being cancelled
+                if (!this.executor.awaitTermination(60, TimeUnit.SECONDS)) {
+                    Debug.logWarning("Unable to shutdown the thread pool for JobPoller " + this.name, module);
+                }
+            }
+        } catch (InterruptedException ie) {
+            // re cancel if current thread was also interrupted
+            this.executor.shutdownNow();
+            // preserve interrupt status
+            Thread.currentThread().interrupt();
+        }
+        Debug.logInfo("Shutdown completed of thread pool for JobPoller " + this.name, module);
     }
 }
-

Modified: ofbiz/branches/jackrabbit20120501/framework/service/src/org/ofbiz/service/job/PersistedServiceJob.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20120501/framework/service/src/org/ofbiz/service/job/PersistedServiceJob.java?rev=1370126&r1=1370125&r2=1370126&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20120501/framework/service/src/org/ofbiz/service/job/PersistedServiceJob.java (original)
+++ ofbiz/branches/jackrabbit20120501/framework/service/src/org/ofbiz/service/job/PersistedServiceJob.java Tue Aug  7 06:25:59 2012
@@ -33,6 +33,7 @@ import org.ofbiz.base.util.UtilDateTime;
 import org.ofbiz.base.util.UtilGenerics;
 import org.ofbiz.base.util.UtilProperties;
 import org.ofbiz.base.util.UtilValidate;
+import org.ofbiz.service.calendar.RecurrenceInfoException;
 import org.ofbiz.service.calendar.TemporalExpression;
 import org.ofbiz.service.calendar.TemporalExpressionWorker;
 import org.ofbiz.entity.Delegator;
@@ -52,19 +53,21 @@ import org.xml.sax.SAXException;
 import org.apache.commons.lang.StringUtils;
 
 /**
- * Entity Service Job - Store => Schedule => Run
+ * A {@link Job} that is backed by the entity engine. Job data is stored
+ * in the JobSandbox entity.
+ * <p>When the job is queued, this object "owns" the entity value. Any external changes
+ * are ignored except the cancelDateTime field - jobs can be canceled after they are queued.</p>
  */
 @SuppressWarnings("serial")
 public class PersistedServiceJob extends GenericServiceJob {
 
     public static final String module = PersistedServiceJob.class.getName();
 
-    private transient Delegator delegator = null;
-    private Timestamp storedDate = null;
+    private final transient Delegator delegator;
     private long nextRecurrence = -1;
-    private long maxRetry = -1;
-    private long currentRetryCount = 0;
-    private boolean warningLogged = false;
+    private final long maxRetry;
+    private final long currentRetryCount;
+    private final GenericValue jobValue;
 
     /**
      * Creates a new PersistedServiceJob
@@ -73,11 +76,10 @@ public class PersistedServiceJob extends
      * @param req
      */
     public PersistedServiceJob(DispatchContext dctx, GenericValue jobValue, GenericRequester req) {
-        super(jobValue.getString("jobId"), jobValue.getString("jobName"));
+        super(dctx, jobValue.getString("jobId"), jobValue.getString("jobName"), null, null, req);
         this.delegator = dctx.getDelegator();
-        this.requester = req;
-        this.dctx = dctx;
-        this.storedDate = jobValue.getTimestamp("runTime");
+        this.jobValue = jobValue;
+        Timestamp storedDate = jobValue.getTimestamp("runTime");
         this.runtime = storedDate.getTime();
         this.maxRetry = jobValue.get("maxRetry") != null ? jobValue.getLong("maxRetry").longValue() : -1;
         Long retryCount = jobValue.getLong("currentRetryCount");
@@ -85,95 +87,75 @@ public class PersistedServiceJob extends
             this.currentRetryCount = retryCount.longValue();
         } else {
             // backward compatibility
-            this.currentRetryCount = PersistedServiceJob.getRetries(jobValue, this.delegator);
+            this.currentRetryCount = getRetries(this.delegator);
         }
-
-        // Debug.logInfo("=============== New PersistedServiceJob, delegator from dctx is [" + dctx.getDelegator().getDelegatorName() + "] and delegator from jobValue is [" + jobValue.getDelegator().getDelegatorName() + "]", module);
     }
 
     @Override
     public void queue() throws InvalidJobException {
         super.queue();
-
-        // refresh the job object
-        GenericValue jobValue = null;
-        try {
-            jobValue = this.getJob();
-            jobValue.refresh();
-        } catch (GenericEntityException e) {
-            runtime = -1;
-            throw new InvalidJobException("Unable to refresh Job object", e);
-        }
-
-        // make sure it isn't already set/cancelled
-        if (runtime != -1) {
-            Timestamp cancelTime = jobValue.getTimestamp("cancelDateTime");
-            Timestamp startTime = jobValue.getTimestamp("startDateTime");
-            if (cancelTime != null || startTime != null) {
-                // job not available
-                runtime = -1;
-                throw new InvalidJobException("Job [" + getJobId() + "] is not available");
-
-            } else {
-                // set the start time to now
-                jobValue.set("startDateTime", UtilDateTime.nowTimestamp());
-                jobValue.set("statusId", "SERVICE_RUNNING");
-                try {
-                    jobValue.store();
-                } catch (GenericEntityException e) {
-                    runtime = -1;
-                    throw new InvalidJobException("Unable to set the startDateTime on the current job [" + getJobId() + "]; not running!", e);
-
-                }
+        Timestamp cancelTime = jobValue.getTimestamp("cancelDateTime");
+        Timestamp startTime = jobValue.getTimestamp("startDateTime");
+        if (cancelTime != null || startTime != null) {
+            // job not available
+            throw new InvalidJobException("Job [" + getJobId() + "] is not available");
+        } else {
+            // set the start time to now
+            jobValue.set("startDateTime", UtilDateTime.nowTimestamp());
+            jobValue.set("statusId", "SERVICE_RUNNING");
+            try {
+                jobValue.store();
+            } catch (GenericEntityException e) {
+                throw new InvalidJobException("Unable to set the startDateTime and statusId on the current job [" + getJobId() + "]; not running!", e);
             }
         }
     }
 
-    /**
-     * @see org.ofbiz.service.job.GenericServiceJob#init()
-     */
     @Override
     protected void init() throws InvalidJobException {
         super.init();
-
-        // configure any addition recurrences
-        GenericValue job = this.getJob();
+        try {
+            // Job might have been canceled after it was placed in the queue.
+            jobValue.refresh();
+        } catch (GenericEntityException e) {
+            throw new InvalidJobException("Unable to refresh JobSandbox value", e);
+        }
+        if (jobValue.getTimestamp("cancelDateTime") != null) {
+            // Job cancelled
+            throw new InvalidJobException("Job [" + getJobId() + "] was cancelled");
+        }
+        String instanceId = UtilProperties.getPropertyValue("general.properties", "unique.instanceId", "ofbiz0");
+        if (!instanceId.equals(jobValue.getString("runByInstanceId"))) {
+            // This condition isn't possible, but we will leave it here.
+            throw new InvalidJobException("Job has been accepted by a different instance!");
+        }
+        // configure any additional recurrences
         long maxRecurrenceCount = -1;
         long currentRecurrenceCount = 0;
         TemporalExpression expr = null;
-        RecurrenceInfo recurrence = JobManager.getRecurrenceInfo(job);
+        RecurrenceInfo recurrence = getRecurrenceInfo();
         if (recurrence != null) {
-            if (!this.warningLogged) {
-                Debug.logWarning("Persisted Job [" + getJobId() + "] references a RecurrenceInfo, recommend using TemporalExpression instead", module);
-                this.warningLogged = true;
-            }
+            Debug.logWarning("Persisted Job [" + getJobId() + "] references a RecurrenceInfo, recommend using TemporalExpression instead", module);
             currentRecurrenceCount = recurrence.getCurrentCount();
             expr = RecurrenceInfo.toTemporalExpression(recurrence);
         }
-        if (expr == null && UtilValidate.isNotEmpty(job.getString("tempExprId"))) {
+        if (expr == null && UtilValidate.isNotEmpty(jobValue.getString("tempExprId"))) {
             try {
-                expr = TemporalExpressionWorker.getTemporalExpression(this.delegator, job.getString("tempExprId"));
+                expr = TemporalExpressionWorker.getTemporalExpression(this.delegator, jobValue.getString("tempExprId"));
             } catch (GenericEntityException e) {
                 throw new RuntimeException(e.getMessage());
             }
         }
-
-        String instanceId = UtilProperties.getPropertyValue("general.properties", "unique.instanceId", "ofbiz0");
-        if (!instanceId.equals(job.getString("runByInstanceId"))) {
-            throw new InvalidJobException("Job has been accepted by a different instance!");
-        }
-
-        if (job.get("maxRecurrenceCount") != null) {
-            maxRecurrenceCount = job.getLong("maxRecurrenceCount").longValue();
+        if (jobValue.get("maxRecurrenceCount") != null) {
+            maxRecurrenceCount = jobValue.getLong("maxRecurrenceCount").longValue();
         }
-        if (job.get("currentRecurrenceCount") != null) {
-            currentRecurrenceCount = job.getLong("currentRecurrenceCount").longValue();
+        if (jobValue.get("currentRecurrenceCount") != null) {
+            currentRecurrenceCount = jobValue.getLong("currentRecurrenceCount").longValue();
         }
         if (maxRecurrenceCount != -1) {
             currentRecurrenceCount++;
-            job.set("currentRecurrenceCount", currentRecurrenceCount);
+            jobValue.set("currentRecurrenceCount", currentRecurrenceCount);
         }
-
         try {
             if (expr != null && (maxRecurrenceCount == -1 || currentRecurrenceCount <= maxRecurrenceCount)) {
                 if (recurrence != null) {
@@ -181,26 +163,25 @@ public class PersistedServiceJob extends
                 }
                 Calendar next = expr.next(Calendar.getInstance());
                 if (next != null) {
-                    createRecurrence(job, next.getTimeInMillis(), false);
+                    createRecurrence(next.getTimeInMillis(), false);
                 }
             }
         } catch (GenericEntityException e) {
-            throw new RuntimeException(e.getMessage());
+            throw new InvalidJobException(e);
         }
         if (Debug.infoOn()) Debug.logInfo("Job  [" + getJobName() + "] Id ["  + getJobId() + "] -- Next runtime: " + new Date(nextRecurrence), module);
     }
 
-    private void createRecurrence(GenericValue job, long next, boolean isRetryOnFailure) throws GenericEntityException {
+    private void createRecurrence(long next, boolean isRetryOnFailure) throws GenericEntityException {
         if (Debug.verboseOn()) Debug.logVerbose("Next runtime returned: " + next, module);
-
         if (next > runtime) {
-            String pJobId = job.getString("parentJobId");
+            String pJobId = jobValue.getString("parentJobId");
             if (pJobId == null) {
-                pJobId = job.getString("jobId");
+                pJobId = jobValue.getString("jobId");
             }
-            GenericValue newJob = GenericValue.create(job);
+            GenericValue newJob = GenericValue.create(jobValue);
             newJob.remove("jobId");
-            newJob.set("previousJobId", job.getString("jobId"));
+            newJob.set("previousJobId", jobValue.getString("jobId"));
             newJob.set("parentJobId", pJobId);
             newJob.set("statusId", "SERVICE_PENDING");
             newJob.set("startDateTime", null);
@@ -217,20 +198,12 @@ public class PersistedServiceJob extends
         }
     }
 
-    /**
-     * @see org.ofbiz.service.job.GenericServiceJob#finish()
-     */
     @Override
     protected void finish(Map<String, Object> result) throws InvalidJobException {
         super.finish(result);
-
         // set the finish date
-        GenericValue job = getJob();
-        String status = job.getString("statusId");
-        if (status == null || "SERVICE_RUNNING".equals(status)) {
-            job.set("statusId", "SERVICE_FINISHED");
-        }
-        job.set("finishDateTime", UtilDateTime.nowTimestamp());
+        jobValue.set("statusId", "SERVICE_FINISHED");
+        jobValue.set("finishDateTime", UtilDateTime.nowTimestamp());
         String jobResult = null;
         if (ServiceUtil.isError(result)) {
             jobResult = StringUtils.substring(ServiceUtil.getErrorMessage(result), 0, 255);
@@ -238,35 +211,29 @@ public class PersistedServiceJob extends
             jobResult = StringUtils.substring(ServiceUtil.makeSuccessMessage(result, "", "", "", ""), 0, 255);
         }
         if (UtilValidate.isNotEmpty(jobResult)) {
-            job.set("jobResult", jobResult);
+            jobValue.set("jobResult", jobResult);
         }
         try {
-            job.store();
+            jobValue.store();
         } catch (GenericEntityException e) {
             Debug.logError(e, "Cannot update the job [" + getJobId() + "] sandbox", module);
         }
     }
 
-    /**
-     * @see org.ofbiz.service.job.GenericServiceJob#failed(Throwable)
-     */
     @Override
     protected void failed(Throwable t) throws InvalidJobException {
         super.failed(t);
-
-        GenericValue job = getJob();
         // if the job has not been re-scheduled; we need to re-schedule and run again
         if (nextRecurrence == -1) {
             if (this.canRetry()) {
                 // create a recurrence
                 Calendar cal = Calendar.getInstance();
-                cal.setTime(new Date());
                 cal.add(Calendar.MINUTE, ServiceConfigUtil.getFailedRetryMin());
                 long next = cal.getTimeInMillis();
                 try {
-                    createRecurrence(job, next, true);
-                } catch (GenericEntityException gee) {
-                    Debug.logError(gee, "ERROR: Unable to re-schedule job [" + getJobId() + "] to re-run : " + job, module);
+                    createRecurrence(next, true);
+                } catch (GenericEntityException e) {
+                    Debug.logError(e, "Unable to re-schedule job [" + getJobId() + "]: ", module);
                 }
                 Debug.logInfo("Persisted Job [" + getJobId() + "] Failed Re-Scheduling : " + next, module);
             } else {
@@ -274,50 +241,40 @@ public class PersistedServiceJob extends
             }
         }
         // set the failed status
-        job.set("statusId", "SERVICE_FAILED");
-        job.set("finishDateTime", UtilDateTime.nowTimestamp());
-        job.set("jobResult", StringUtils.substring(t.getMessage(), 0, 255));
+        jobValue.set("statusId", "SERVICE_FAILED");
+        jobValue.set("finishDateTime", UtilDateTime.nowTimestamp());
+        jobValue.set("jobResult", StringUtils.substring(t.getMessage(), 0, 255));
         try {
-            job.store();
+            jobValue.store();
         } catch (GenericEntityException e) {
-            Debug.logError(e, "Cannot update the job sandbox", module);
+            Debug.logError(e, "Cannot update the JobSandbox entity", module);
         }
     }
 
-    /**
-     * @see org.ofbiz.service.job.GenericServiceJob#getServiceName()
-     */
     @Override
     protected String getServiceName() throws InvalidJobException {
-        GenericValue jobObj = getJob();
-        if (jobObj == null || jobObj.get("serviceName") == null) {
+        if (jobValue == null || jobValue.get("serviceName") == null) {
             return null;
         }
-        return jobObj.getString("serviceName");
+        return jobValue.getString("serviceName");
     }
 
-    /**
-     * @see org.ofbiz.service.job.GenericServiceJob#getContext()
-     */
     @Override
     protected Map<String, Object> getContext() throws InvalidJobException {
         Map<String, Object> context = null;
         try {
-            GenericValue jobObj = getJob();
-            if (!UtilValidate.isEmpty(jobObj.getString("runtimeDataId"))) {
-                GenericValue contextObj = jobObj.getRelatedOne("RuntimeData", false);
+            if (!UtilValidate.isEmpty(jobValue.getString("runtimeDataId"))) {
+                GenericValue contextObj = jobValue.getRelatedOne("RuntimeData", false);
                 if (contextObj != null) {
                     context = UtilGenerics.checkMap(XmlSerializer.deserialize(contextObj.getString("runtimeInfo"), delegator), String.class, Object.class);
                 }
             }
-
             if (context == null) {
                 context = FastMap.newInstance();
             }
-
             // check the runAsUser
-            if (!UtilValidate.isEmpty(jobObj.get("runAsUser"))) {
-                context.put("userLogin", ServiceUtil.getUserLogin(dctx, context, jobObj.getString("runAsUser")));
+            if (!UtilValidate.isEmpty(jobValue.getString("runAsUser"))) {
+                context.put("userLogin", ServiceUtil.getUserLogin(dctx, context, jobValue.getString("runAsUser")));
             }
         } catch (GenericEntityException e) {
             Debug.logError(e, "PersistedServiceJob.getContext(): Entity Exception", module);
@@ -333,46 +290,45 @@ public class PersistedServiceJob extends
         if (context == null) {
             Debug.logError("Job context is null", module);
         }
-
         return context;
     }
 
-    // gets the job value object
-    private GenericValue getJob() throws InvalidJobException {
-        try {
-            GenericValue jobObj = delegator.findOne("JobSandbox", false, "jobId", getJobId());
-
-            if (jobObj == null) {
-                throw new InvalidJobException("Job [" + getJobId() + "] came back null from datasource from delegator " + delegator.getDelegatorName());
-            }
-            return jobObj;
-        } catch (GenericEntityException e) {
-            throw new InvalidJobException("Cannot get job definition [" + getJobId() + "] from entity", e);
-        }
-    }
-
     // returns the number of current retries
-    private static long getRetries(GenericValue job, Delegator delegator) {
-        String pJobId = job.getString("parentJobId");
+    private long getRetries(Delegator delegator) {
+        String pJobId = jobValue.getString("parentJobId");
         if (pJobId == null) {
             return 0;
         }
-
         long count = 0;
         try {
             EntityFieldMap ecl = EntityCondition.makeConditionMap("parentJobId", pJobId, "statusId", "SERVICE_FAILED");
             count = delegator.findCountByCondition("JobSandbox", ecl, null, null);
         } catch (GenericEntityException e) {
-            Debug.logError(e, module);
+            Debug.logError(e, "Exception thrown while counting retries: ", module);
         }
-
         return count + 1; // add one for the parent
     }
 
-    private boolean canRetry() throws InvalidJobException {
+    private boolean canRetry() {
         if (maxRetry == -1) {
             return true;
         }
         return currentRetryCount < maxRetry;
     }
+
+    private RecurrenceInfo getRecurrenceInfo() {
+        try {
+            if (UtilValidate.isNotEmpty(jobValue.getString("recurrenceInfoId"))) {
+                GenericValue ri = jobValue.getRelatedOne("RecurrenceInfo", false);
+                if (ri != null) {
+                    return new RecurrenceInfo(ri);
+                }
+            }
+        } catch (GenericEntityException e) {
+            Debug.logError(e, "Problem getting RecurrenceInfo entity from JobSandbox", module);
+        } catch (RecurrenceInfoException re) {
+            Debug.logError(re, "Problem creating RecurrenceInfo instance: " + re.getMessage(), module);
+        }
+        return null;
+    }
 }

Modified: ofbiz/branches/jackrabbit20120501/framework/service/src/org/ofbiz/service/mail/JavaMailContainer.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20120501/framework/service/src/org/ofbiz/service/mail/JavaMailContainer.java?rev=1370126&r1=1370125&r2=1370126&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20120501/framework/service/src/org/ofbiz/service/mail/JavaMailContainer.java (original)
+++ ofbiz/branches/jackrabbit20120501/framework/service/src/org/ofbiz/service/mail/JavaMailContainer.java Tue Aug  7 06:25:59 2012
@@ -22,8 +22,9 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
-import java.util.Timer;
-import java.util.TimerTask;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
 import javax.mail.FetchProfile;
 import javax.mail.Flags;
 import javax.mail.Folder;
@@ -48,9 +49,9 @@ import org.ofbiz.entity.Delegator;
 import org.ofbiz.entity.DelegatorFactory;
 import org.ofbiz.entity.GenericValue;
 import org.ofbiz.entity.GenericEntityException;
-import org.ofbiz.service.GenericDispatcher;
 import org.ofbiz.service.LocalDispatcher;
 import org.ofbiz.service.GenericServiceException;
+import org.ofbiz.service.ServiceContainer;
 
 public class JavaMailContainer implements Container {
 
@@ -62,12 +63,12 @@ public class JavaMailContainer implement
     protected GenericValue userLogin = null;
     protected long timerDelay = 300000;
     protected long maxSize = 1000000;
-    protected Timer pollTimer = null;
+    protected ScheduledExecutorService pollTimer = null;
     protected boolean deleteMail = false;    // whether to delete emails after fetching them.
 
     protected String configFile = null;
     protected Map<Store, Session> stores = null;
-
+    private String name;
     /**
      * Initialize the container
      *
@@ -76,10 +77,11 @@ public class JavaMailContainer implement
      * @throws org.ofbiz.base.container.ContainerException
      *
      */
-    public void init(String[] args, String configFile) throws ContainerException {
+    public void init(String[] args, String name, String configFile) throws ContainerException {
+        this.name = name;
         this.configFile = configFile;
         this.stores = new LinkedHashMap<Store, Session>();
-        this.pollTimer = new Timer();
+        this.pollTimer = Executors.newScheduledThreadPool(1);
     }
 
     /**
@@ -90,13 +92,13 @@ public class JavaMailContainer implement
      *
      */
     public boolean start() throws ContainerException {
-        ContainerConfig.Container cfg = ContainerConfig.getContainer("javamail-container", configFile);
+        ContainerConfig.Container cfg = ContainerConfig.getContainer(name, configFile);
         String dispatcherName = ContainerConfig.getPropertyValue(cfg, "dispatcher-name", "JavaMailDispatcher");
         String delegatorName = ContainerConfig.getPropertyValue(cfg, "delegator-name", "default");
         this.deleteMail = "true".equals(ContainerConfig.getPropertyValue(cfg, "delete-mail", "false"));
 
         this.delegator = DelegatorFactory.getDelegator(delegatorName);
-        this.dispatcher = GenericDispatcher.getLocalDispatcher(dispatcherName, delegator);
+        this.dispatcher = ServiceContainer.getLocalDispatcher(dispatcherName, delegator);
         this.timerDelay = ContainerConfig.getPropertyValue(cfg, "poll-delay", 300000);
         this.maxSize = ContainerConfig.getPropertyValue(cfg, "maxSize", 1000000); // maximum size in bytes
 
@@ -125,7 +127,7 @@ public class JavaMailContainer implement
 
         // start the polling timer
         if (UtilValidate.isNotEmpty(stores)) {
-            pollTimer.schedule(new PollerTask(dispatcher, userLogin), timerDelay, timerDelay);
+            pollTimer.scheduleAtFixedRate(new PollerTask(dispatcher, userLogin), timerDelay, timerDelay, TimeUnit.MILLISECONDS);
         } else {
             Debug.logWarning("No JavaMail Store(s) configured; poller disabled.", module);
         }
@@ -141,10 +143,14 @@ public class JavaMailContainer implement
      */
     public void stop() throws ContainerException {
         // stop the poller
-        this.pollTimer.cancel();
+        this.pollTimer.shutdown();
         Debug.logWarning("stop JavaMail poller", module);
     }
 
+    public String getName() {
+        return name;
+    }
+
     // java-mail methods
     protected Session makeSession(ContainerConfig.Container.Property client) {
         Properties props = new Properties();
@@ -245,7 +251,7 @@ public class JavaMailContainer implement
         }
     }
 
-    class PollerTask extends TimerTask {
+    class PollerTask implements Runnable {
 
         LocalDispatcher dispatcher;
         GenericValue userLogin;
@@ -255,7 +261,6 @@ public class JavaMailContainer implement
             this.userLogin = userLogin;
         }
 
-        @Override
         public void run() {
             if (UtilValidate.isNotEmpty(stores)) {
                 for (Map.Entry<Store, Session> entry: stores.entrySet()) {

Modified: ofbiz/branches/jackrabbit20120501/framework/service/src/org/ofbiz/service/rmi/RmiServiceContainer.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20120501/framework/service/src/org/ofbiz/service/rmi/RmiServiceContainer.java?rev=1370126&r1=1370125&r2=1370126&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20120501/framework/service/src/org/ofbiz/service/rmi/RmiServiceContainer.java (original)
+++ ofbiz/branches/jackrabbit20120501/framework/service/src/org/ofbiz/service/rmi/RmiServiceContainer.java Tue Aug  7 06:25:59 2012
@@ -32,8 +32,8 @@ import org.ofbiz.base.container.Containe
 import org.ofbiz.base.util.UtilValidate;
 import org.ofbiz.entity.Delegator;
 import org.ofbiz.entity.DelegatorFactory;
-import org.ofbiz.service.GenericDispatcher;
 import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.ServiceContainer;
 
 /**
  * RMI Service Engine Container / Dispatcher
@@ -45,19 +45,18 @@ public class RmiServiceContainer impleme
     protected RemoteDispatcherImpl remote = null;
     protected String configFile = null;
     protected String name = null;
-
+    private String containerName;
     // Container methods
 
-    /**
-     * @see org.ofbiz.base.container.Container#init(java.lang.String[], java.lang.String)
-     */
-    public void init(String[] args, String configFile) {
+    @Override
+    public void init(String[] args, String name, String configFile) {
+        this.containerName = name;
         this.configFile = configFile;
     }
 
     public boolean start() throws ContainerException {
         // get the container config
-        ContainerConfig.Container cfg = ContainerConfig.getContainer("rmi-dispatcher", configFile);
+        ContainerConfig.Container cfg = ContainerConfig.getContainer(containerName, configFile);
         ContainerConfig.Container.Property initialCtxProp = cfg.getProperty("use-initial-context");
         ContainerConfig.Container.Property lookupHostProp = cfg.getProperty("bound-host");
         ContainerConfig.Container.Property lookupPortProp = cfg.getProperty("bound-port");
@@ -125,7 +124,7 @@ public class RmiServiceContainer impleme
         Delegator delegator = DelegatorFactory.getDelegator(delegatorProp.value);
 
         // create the LocalDispatcher
-        LocalDispatcher dispatcher = GenericDispatcher.getLocalDispatcher(name, delegator);
+        LocalDispatcher dispatcher = ServiceContainer.getLocalDispatcher(name, delegator);
 
         // create the RemoteDispatcher
         try {
@@ -170,4 +169,8 @@ public class RmiServiceContainer impleme
     public void stop() throws ContainerException {
         remote.deregister();
     }
+
+    public String getName() {
+        return containerName;
+    }
 }

Modified: ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/Config.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/Config.java?rev=1370126&r1=1370125&r2=1370126&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/Config.java (original)
+++ ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/Config.java Tue Aug  7 06:25:59 2012
@@ -25,8 +25,10 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.InetAddress;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Properties;
 import java.util.TimeZone;
 
@@ -71,7 +73,7 @@ public class Config {
     public String containerConfig;
     public String instrumenterClassName;
     public String instrumenterFile;
-    public List<String> loaders;
+    public List<Map> loaders;
     public String logDir;
     public String ofbizHome;
     public boolean requireCommJar = false;
@@ -209,8 +211,6 @@ public class Config {
                     fis = new FileInputStream(propsFile);
                     if (fis != null) {
                         props.load(fis);
-                    } else {
-                        throw new FileNotFoundException();
                     }
                 } catch (FileNotFoundException e2) {
                     // do nothing; we will see empty props below
@@ -420,14 +420,18 @@ public class Config {
         instrumenterFile = getProp(props, "ofbiz.instrumenterFile", null);
 
         // loader classes
-        loaders = new ArrayList<String>();
+        loaders = new ArrayList<Map>();
         int currentPosition = 1;
+        Map<String, String> loader = null;
         while (true) {
+            loader = new HashMap<String, String>();
             String loaderClass = props.getProperty("ofbiz.start.loader" + currentPosition);
             if (loaderClass == null || loaderClass.length() == 0) {
                 break;
             } else {
-                loaders.add(loaderClass);
+                loader.put("class", loaderClass);
+                loader.put("profiles", props.getProperty("ofbiz.start.loader" + currentPosition + ".loaders"));
+                loaders.add(loader);
                 currentPosition++;
             }
         }

Modified: ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/InstrumenterWorker.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/InstrumenterWorker.java?rev=1370126&r1=1370125&r2=1370126&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/InstrumenterWorker.java (original)
+++ ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/InstrumenterWorker.java Tue Aug  7 06:25:59 2012
@@ -26,7 +26,7 @@ import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.lang.management.ManagementFactory;
+import java.lang.Runtime;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.util.List;
@@ -73,7 +73,7 @@ public final class InstrumenterWorker {
         } catch (ClassNotFoundException e) {
             return srcPaths;
         }
-        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(ManagementFactory.getOperatingSystemMXBean().getAvailableProcessors());
+        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(Runtime.getRuntime().availableProcessors());
         try {
             File instrumenterFile = new File(instrumenterFileName);
             instrumenterFile.delete();

Modified: ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/Start.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/Start.java?rev=1370126&r1=1370125&r2=1370126&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/Start.java (original)
+++ ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/Start.java Tue Aug  7 06:25:59 2012
@@ -31,6 +31,7 @@ import java.net.Socket;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.atomic.AtomicReference;
 
 /**
@@ -253,11 +254,12 @@ public class Start {
         ClassLoader classloader = Thread.currentThread().getContextClassLoader();
         synchronized (this.loaders) {
             // initialize the loaders
-            for (String loaderClassName: config.loaders) {
+            for (Map loaderMap: config.loaders) {
                 if (this.serverState.get() == ServerState.STOPPING) {
                     return;
                 }
                 try {
+                    String loaderClassName = (String)loaderMap.get("class");
                     Class<?> loaderClass = classloader.loadClass(loaderClassName);
                     StartupLoader loader = (StartupLoader) loaderClass.newInstance();
                     loader.load(config, loaderArgs.toArray(new String[loaderArgs.size()]));
@@ -398,7 +400,7 @@ public class Start {
         private ServerSocket serverSocket = null;
 
         AdminPortThread() throws StartupException {
-            super("AdminPortThread");
+            super("OFBiz-AdminPortThread");
             try {
                 this.serverSocket = new ServerSocket(config.adminPort, 1, config.adminAddress);
             } catch (IOException e) {

Modified: ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/both.properties
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/both.properties?rev=1370126&r1=1370125&r2=1370126&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/both.properties (original)
+++ ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/both.properties Tue Aug  7 06:25:59 2012
@@ -46,6 +46,7 @@ ofbiz.start.loader1=org.ofbiz.base.splas
 
 # --- StartupLoader implementations to load (in order)
 ofbiz.start.loader2=org.ofbiz.base.container.ContainerLoader
+ofbiz.start.loader2.loaders=main,pos,rmi
 
 # -- Splash Logo
 ofbiz.start.splash.logo=framework/images/webapp/images/ofbiz_logo.gif

Modified: ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/install.properties
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/install.properties?rev=1370126&r1=1370125&r2=1370126&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/install.properties (original)
+++ ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/install.properties Tue Aug  7 06:25:59 2012
@@ -39,10 +39,11 @@
 #ofbiz.log.dir=runtime/logs
 
 # --- Location (relative to ofbiz.home) for (normal) container configuration
-ofbiz.container.config=framework/base/config/install-containers.xml
+#ofbiz.container.config=framework/base/config/ofbiz-containers.xml
 
 # --- StartupLoader implementations to load (in order)
 ofbiz.start.loader1=org.ofbiz.base.container.ContainerLoader
+ofbiz.start.loader1.loaders=install
 
 # -- Enable the shutdown hook
 #ofbiz.enable.hook=false

Modified: ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/jetty.properties
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/jetty.properties?rev=1370126&r1=1370125&r2=1370126&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/jetty.properties (original)
+++ ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/jetty.properties Tue Aug  7 06:25:59 2012
@@ -48,10 +48,11 @@ ofbiz.admin.key=so3du5kasd5dn
 #ofbiz.log.dir=runtime/logs
 
 # --- Location (relative to ofbiz.home) for (normal) container configuration
-ofbiz.container.config=framework/base/config/jetty-containers.xml
+#ofbiz.container.config=framework/base/config/ofbiz-containers.xml
 
 # --- StartupLoader implementations to load (in order)
 ofbiz.start.loader1=org.ofbiz.base.container.ContainerLoader
+ofbiz.start.loader1.loaders=main,rmi
 
 # -- Enable the shutdown hook
 ofbiz.enable.hook=true

Modified: ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/pos.properties
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/pos.properties?rev=1370126&r1=1370125&r2=1370126&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/pos.properties (original)
+++ ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/pos.properties Tue Aug  7 06:25:59 2012
@@ -39,13 +39,14 @@
 #ofbiz.log.dir=runtime/logs
 
 # --- Location (relative to ofbiz.home) for (normal) container configuration
-ofbiz.container.config=framework/base/config/pos-containers.xml
+#ofbiz.container.config=framework/base/config/ofbiz-containers.xml
 
 # -- StartupLoader implementation for Splash Screen
 ofbiz.start.loader1=org.ofbiz.base.splash.SplashLoader
 
 # --- StartupLoader implementations to load (in order)
 ofbiz.start.loader2=org.ofbiz.base.container.ContainerLoader
+ofbiz.start.loader2.loaders=pos
 
 # -- Splash Logo
 ofbiz.start.splash.logo=framework/images/webapp/images/ofbiz_logo.gif

Modified: ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/rmi.properties
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/rmi.properties?rev=1370126&r1=1370125&r2=1370126&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/rmi.properties (original)
+++ ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/rmi.properties Tue Aug  7 06:25:59 2012
@@ -39,10 +39,11 @@
 #ofbiz.log.dir=runtime/logs
 
 # --- Location (relative to ofbiz.home) for (normal) container configuration
-ofbiz.container.config=framework/base/config/rmi-containers.xml
+#ofbiz.container.config=framework/base/config/ofbiz-containers.xml
 
 # --- StartupLoader implementations to load (in order)
 ofbiz.start.loader1=org.ofbiz.base.container.ContainerLoader
+ofbiz.start.loader1.loaders=rmi
 
 # -- Enable the shutdown hook
 #ofbiz.enable.hook=true

Modified: ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/start.properties
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/start.properties?rev=1370126&r1=1370125&r2=1370126&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/start.properties (original)
+++ ofbiz/branches/jackrabbit20120501/framework/start/src/org/ofbiz/base/start/start.properties Tue Aug  7 06:25:59 2012
@@ -52,6 +52,7 @@ ofbiz.admin.key=so3du5kasd5dn
 
 # --- StartupLoader implementations to load (in order)
 ofbiz.start.loader1=org.ofbiz.base.container.ContainerLoader
+ofbiz.start.loader1.loaders=main,rmi
 
 # -- Enable the shutdown hook
 #ofbiz.enable.hook=true