You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by er...@apache.org on 2012/10/25 07:04:29 UTC

svn commit: r1401975 [25/29] - in /ofbiz/branches/20120329_portletWidget: ./ applications/accounting/config/ applications/accounting/data/ applications/accounting/script/org/ofbiz/accounting/invoice/ applications/accounting/script/org/ofbiz/accounting/...

Modified: ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/job/JobPoller.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/job/JobPoller.java?rev=1401975&r1=1401974&r2=1401975&view=diff
==============================================================================
--- ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/job/JobPoller.java (original)
+++ ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/job/JobPoller.java Thu Oct 25 05:04:09 2012
@@ -19,204 +19,278 @@
 package org.ofbiz.service.job;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
 
+import org.ofbiz.base.start.Start;
+import org.ofbiz.base.util.Assert;
 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 final class JobPoller implements Runnable {
+public final class JobPoller {
 
     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 POLL_WAIT = 20000;
-    public static final long THREAD_TTL = 18000000;
-
-    private final JobManager jm;
-    private final ThreadPoolExecutor executor;
-    private final String name;
-    private boolean enabled = false;
+    private static final AtomicInteger created = new AtomicInteger();
+    private static final int MIN_THREADS = 1; // Must be no less than one or the executor will shut down.
+    private static final int MAX_THREADS = 5; // Values higher than 5 might slow things down.
+    private static final int POLL_WAIT = 30000; // Database polling interval - 30 seconds.
+    private static final int QUEUE_SIZE = 100;
+    private static final long THREAD_TTL = 120000; // Idle thread lifespan - 2 minutes.
+    private static final ConcurrentHashMap<String, JobManager> jobManagers = new ConcurrentHashMap<String, JobManager>();
+    private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(minThreads(), maxThreads(), getTTL(),
+            TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(queueSize()), new JobInvokerThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
+    private static final JobPoller instance = new JobPoller();
 
     /**
-     * Creates a new JobScheduler
-     * 
-     * @param jm
-     *            JobManager associated with this scheduler
+     * Returns the <code>JobPoller</code> instance.
      */
-    public JobPoller(JobManager jm) {
-        this.name = jm.getDelegator().getDelegatorName();
-        this.jm = jm;
-        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 thread = new Thread(this, "OFBiz-JobPoller-" + this.name);
-                thread.setDaemon(false);
-                // start the poller
-                thread.start();
+    public static JobPoller getInstance() {
+        return instance;
+    }
+
+    private static long getTTL() {
+        String threadTTLAttr = ServiceConfigUtil.getElementAttr("thread-pool", "ttl");
+        if (!threadTTLAttr.isEmpty()) {
+            try {
+                int threadTTL = Integer.parseInt(threadTTLAttr);
+                if (threadTTL > 0) {
+                    return threadTTL;
+                }
+            } catch (NumberFormatException e) {
+                Debug.logError("Exception thrown while parsing thread TTL from serviceengine.xml file [" + e + "]. Using default value.", module);
             }
         }
+        return THREAD_TTL;
+    }
+
+    private static int maxThreads() {
+        String maxThreadsAttr = ServiceConfigUtil.getElementAttr("thread-pool", "max-threads");
+        if (!maxThreadsAttr.isEmpty()) {
+            try {
+                int maxThreads = Integer.parseInt(maxThreadsAttr);
+                if (maxThreads > 0) {
+                    return maxThreads;
+                }
+            } catch (NumberFormatException e) {
+                Debug.logError("Exception thrown while parsing maximum threads from serviceengine.xml file [" + e + "]. Using default value.", module);
+            }
+        }
+        return MAX_THREADS;
+    }
+
+    private static int minThreads() {
+        String minThreadsAttr = ServiceConfigUtil.getElementAttr("thread-pool", "min-threads");
+        if (!minThreadsAttr.isEmpty()) {
+            try {
+                int minThreads = Integer.parseInt(minThreadsAttr);
+                if (minThreads > 0) {
+                    return minThreads;
+                }
+            } catch (NumberFormatException e) {
+                Debug.logError("Exception thrown while parsing minimum threads from serviceengine.xml file [" + e + "]. Using default value.", module);
+            }
+        }
+        return MIN_THREADS;
+    }
+
+    private static int pollWaitTime() {
+        String pollIntervalAttr = ServiceConfigUtil.getElementAttr("thread-pool", "poll-db-millis");
+        if (!pollIntervalAttr.isEmpty()) {
+            try {
+                int pollInterval = Integer.parseInt(pollIntervalAttr);
+                if (pollInterval > 0) {
+                    return pollInterval;
+                }
+            } catch (NumberFormatException e) {
+                Debug.logError("Exception thrown while parsing database polling interval from serviceengine.xml file [" + e + "]. Using default value.", module);
+            }
+        }
+        return POLL_WAIT;
+    }
+
+    private static int queueSize() {
+        String queueSizeAttr = ServiceConfigUtil.getElementAttr("thread-pool", "jobs");
+        if (!queueSizeAttr.isEmpty()) {
+            try {
+                int queueSize = Integer.parseInt(queueSizeAttr);
+                if (queueSize > 0) {
+                    return queueSize;
+                }
+            } catch (NumberFormatException e) {
+                Debug.logError("Exception thrown while parsing queue size from serviceengine.xml file [" + e + "]. Using default value.", module);
+            }
+        }
+        return QUEUE_SIZE;
     }
 
     /**
-     * Returns the JobManager
+     * Register a {@link JobManager} with the job poller.
+     * 
+     * @param jm The <code>JobManager</code> to register.
+     * @throws IllegalArgumentException if <code>jm</code> is null
      */
-    public JobManager getManager() {
-        return jm;
+    public static void registerJobManager(JobManager jm) {
+        Assert.notNull("jm", jm);
+        jobManagers.putIfAbsent(jm.getDelegator().getDelegatorName(), jm);
+    }
+
+    // -------------------------------------- //
+
+    private final Thread jobManagerPollerThread;
+
+    private JobPoller() {
+        if (pollEnabled()) {
+            jobManagerPollerThread = new Thread(new JobManagerPoller(), "OFBiz-JobPoller");
+            jobManagerPollerThread.setDaemon(false);
+            jobManagerPollerThread.start();
+        } else {
+            jobManagerPollerThread = null;
+        }
     }
 
+    /**
+     * Returns a <code>Map</code> containing <code>JobPoller</code> statistics.
+     */
     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();
+        poolState.put("keepAliveTimeInSeconds", executor.getKeepAliveTime(TimeUnit.SECONDS));
+        poolState.put("numberOfCoreInvokerThreads", executor.getCorePoolSize());
+        poolState.put("currentNumberOfInvokerThreads", executor.getPoolSize());
+        poolState.put("numberOfActiveInvokerThreads", executor.getActiveCount());
+        poolState.put("maxNumberOfInvokerThreads", executor.getMaximumPoolSize());
+        poolState.put("greatestNumberOfInvokerThreads", executor.getLargestPoolSize());
+        poolState.put("numberOfCompletedTasks", executor.getCompletedTaskCount());
+        BlockingQueue<Runnable> queue = 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;
+            Job job = (Job) 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());
+            taskInfo.put("id", job.getJobId());
+            taskInfo.put("name", job.getJobName());
+            String serviceName = "";
+            if (job instanceof GenericServiceJob) {
+                serviceName = ((GenericServiceJob) job).getServiceName();
+            }
+            taskInfo.put("serviceName", serviceName);
+            taskInfo.put("time", job.getStartTime());
+            taskInfo.put("runtime", job.getRuntime());
             taskList.add(taskInfo);
         }
         poolState.put("taskList", taskList);
         return poolState;
     }
 
-    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 ttl;
+    private boolean pollEnabled() {
+        String enabled = ServiceConfigUtil.getElementAttr("thread-pool", "poll-enabled");
+        return !"false".equalsIgnoreCase(enabled);
     }
 
-    private int maxThreads() {
-        int max = MAX_THREADS;
+    /**
+     * Adds a job to the job 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();
         try {
-            max = Integer.parseInt(ServiceConfigUtil.getElementAttr("thread-pool", "max-threads"));
-        } catch (NumberFormatException nfe) {
-            Debug.logError("Problems reading values from serviceengine.xml file [" + nfe.toString() + "]. Using defaults.", module);
+            executor.execute(job);
+        } catch (Exception e) {
+            job.deQueue();
         }
-        return max;
     }
 
-    private int minThreads() {
-        int min = MIN_THREADS;
-        try {
-            min = Integer.parseInt(ServiceConfigUtil.getElementAttr("thread-pool", "min-threads"));
-        } catch (NumberFormatException nfe) {
-            Debug.logError("Problems reading values from serviceengine.xml file [" + nfe.toString() + "]. Using defaults.", module);
+    /**
+     * Stops the <code>JobPoller</code>. This method is called when OFBiz shuts down.
+     * The <code>JobPoller</code> cannot be restarted.
+     */
+    public void stop() {
+        Debug.logInfo("Shutting down JobPoller.", module);
+        if (jobManagerPollerThread != null) {
+            jobManagerPollerThread.interrupt();
         }
-        return min;
+        List<Runnable> queuedJobs = executor.shutdownNow();
+        for (Runnable task : queuedJobs) {
+            try {
+                Job queuedJob = (Job) task;
+                queuedJob.deQueue();
+            } catch (Exception e) {
+                Debug.logWarning(e, module);
+            }
+        }
+        Debug.logInfo("JobPoller shutdown completed.", module);
     }
 
-    private boolean pollEnabled() {
-        String enabled = ServiceConfigUtil.getElementAttr("thread-pool", "poll-enabled");
-        if (enabled.equalsIgnoreCase("false"))
-            return false;
-        return true;
-    }
+    private static class JobInvokerThreadFactory implements ThreadFactory {
 
-    private int pollWaitTime() {
-        int poll = POLL_WAIT;
-        try {
-            poll = Integer.parseInt(ServiceConfigUtil.getElementAttr("thread-pool", "poll-db-millis"));
-        } catch (NumberFormatException nfe) {
-            Debug.logError("Problems reading values from serviceengine.xml file [" + nfe.toString() + "]. Using defaults.", module);
+        public Thread newThread(Runnable runnable) {
+            return new Thread(runnable, "OFBiz-JobQueue-" + created.getAndIncrement());
         }
-        return poll;
     }
 
-    /**
-     * Adds a job to the RUN queue.
-     * @throws RejectedExecutionException if the poller is stopped.
-     */
-    public void queueNow(Job job) {
-        this.executor.execute(new JobInvoker(job));
-    }
+    // Polls all registered JobManagers for jobs to queue.
+    private class JobManagerPoller implements Runnable {
 
-    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();
-                // 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);
+        // Do not check for interrupts in this method. The design requires the
+        // thread to complete the job manager poll uninterrupted.
+        public void run() {
+            Debug.logInfo("JobPoller thread started.", module);
+            try {
+                while (Start.getInstance().getCurrentState() != Start.ServerState.RUNNING) {
+                    Thread.sleep(1000);
+                }
+                while (!executor.isShutdown()) {
+                    int remainingCapacity = executor.getQueue().remainingCapacity();
+                    if (remainingCapacity > 0) {
+                        // Build "list of lists"
+                        Collection<JobManager> jmCollection = jobManagers.values();
+                        List<Iterator<Job>> pollResults = new ArrayList<Iterator<Job>>();
+                        for (JobManager jm : jmCollection) {
+                            pollResults.add(jm.poll(remainingCapacity).iterator());
+                        }
+                        // Create queue candidate list from "list of lists"
+                        List<Job> queueCandidates = new ArrayList<Job>();
+                        boolean addingJobs = true;
+                        while (addingJobs) {
+                            addingJobs = false;
+                            for (Iterator<Job> jobIterator : pollResults) {
+                                if (jobIterator.hasNext()) {
+                                    queueCandidates.add(jobIterator.next());
+                                    addingJobs = true;
+                                }
+                            }
+                        }
+                        // The candidate list might be larger than the queue remaining capacity,
+                        // but that is okay - the excess jobs will be dequeued and rescheduled.
+                        for (Job job : queueCandidates) {
+                            try {
+                                queueNow(job);
+                            } catch (InvalidJobException e) {
+                                Debug.logError(e, module);
+                            }
+                        }
                     }
+                    Thread.sleep(pollWaitTime());
                 }
-                // NOTE: using sleep instead of wait for stricter locking
-                java.lang.Thread.sleep(pollWaitTime());
             } catch (InterruptedException e) {
-                Debug.logError(e, module);
-                stop();
+                // Happens when JobPoller shuts down - nothing to do.
+                Thread.currentThread().interrupt();
             }
+            Debug.logInfo("JobPoller thread stopped.", module);
         }
-        Debug.logInfo("JobPoller " + this.name + " thread terminated.", module);
-    }
-
-    /**
-     * 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/20120329_portletWidget/framework/service/src/org/ofbiz/service/job/PersistedServiceJob.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/job/PersistedServiceJob.java?rev=1401975&r1=1401974&r2=1401975&view=diff
==============================================================================
--- ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/job/PersistedServiceJob.java (original)
+++ ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/job/PersistedServiceJob.java Thu Oct 25 05:04:09 2012
@@ -20,7 +20,6 @@ package org.ofbiz.service.job;
 
 import java.io.IOException;
 import java.sql.Timestamp;
-import com.ibm.icu.util.Calendar;
 import java.util.Date;
 import java.util.Map;
 
@@ -28,13 +27,11 @@ import javax.xml.parsers.ParserConfigura
 
 import javolution.util.FastMap;
 
+import org.apache.commons.lang.StringUtils;
 import org.ofbiz.base.util.Debug;
 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.TemporalExpression;
-import org.ofbiz.service.calendar.TemporalExpressionWorker;
 import org.ofbiz.entity.Delegator;
 import org.ofbiz.entity.GenericEntityException;
 import org.ofbiz.entity.GenericValue;
@@ -46,25 +43,31 @@ import org.ofbiz.service.DispatchContext
 import org.ofbiz.service.GenericRequester;
 import org.ofbiz.service.ServiceUtil;
 import org.ofbiz.service.calendar.RecurrenceInfo;
+import org.ofbiz.service.calendar.RecurrenceInfoException;
+import org.ofbiz.service.calendar.TemporalExpression;
+import org.ofbiz.service.calendar.TemporalExpressionWorker;
 import org.ofbiz.service.config.ServiceConfigUtil;
 import org.xml.sax.SAXException;
 
-import org.apache.commons.lang.StringUtils;
+import com.ibm.icu.util.Calendar;
 
 /**
- * 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;
+    private final long startTime;
 
     /**
      * Creates a new PersistedServiceJob
@@ -73,107 +76,102 @@ 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.runtime = storedDate.getTime();
+        this.jobValue = jobValue;
+        Timestamp storedDate = jobValue.getTimestamp("runTime");
+        this.startTime = storedDate.getTime();
         this.maxRetry = jobValue.get("maxRetry") != null ? jobValue.getLong("maxRetry").longValue() : -1;
         Long retryCount = jobValue.getLong("currentRetryCount");
         if (retryCount != null) {
             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);
+            throw new InvalidJobException("Unable to refresh JobSandbox value", 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);
-
-                }
+        if (!JobManager.instanceId.equals(jobValue.getString("runByInstanceId"))) {
+            throw new InvalidJobException("Job has been accepted by a different instance");
+        }
+        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 {
+            jobValue.set("statusId", "SERVICE_QUEUED");
+            try {
+                jobValue.store();
+            } catch (GenericEntityException e) {
+                throw new InvalidJobException("Unable to set the startDateTime and statusId on the current job [" + getJobId() + "]; not running!", e);
+            }
+            if (Debug.verboseOn()) {
+                Debug.logVerbose("Placing job [" + getJobId() + "] in queue", module);
             }
         }
     }
 
-    /**
-     * @see org.ofbiz.service.job.GenericServiceJob#init()
-     */
     @Override
     protected void init() throws InvalidJobException {
         super.init();
-
-        // configure any addition recurrences
-        GenericValue job = this.getJob();
+        try {
+            jobValue.refresh();
+        } catch (GenericEntityException e) {
+            throw new InvalidJobException("Unable to refresh JobSandbox value", e);
+        }
+        if (!JobManager.instanceId.equals(jobValue.getString("runByInstanceId"))) {
+            throw new InvalidJobException("Job has been accepted by a different instance");
+        }
+        if (jobValue.getTimestamp("cancelDateTime") != null) {
+            // Job cancelled
+            throw new InvalidJobException("Job [" + getJobId() + "] was cancelled");
+        }
+        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);
+        }
+        if (Debug.verboseOn()) {
+            Debug.logVerbose("Job [" + getJobId() + "] running", module);
+        }
+        // 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 +179,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");
+        if (next > startTime) {
+            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 +214,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 +227,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 +257,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) {
+    protected String getServiceName() {
+        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 +306,70 @@ 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;
+    }
+
+    @Override
+    public void deQueue() throws InvalidJobException {
+        if (currentState != State.QUEUED) {
+            throw new InvalidJobException("Illegal state change");
+        }
+        currentState = State.CREATED;
+        try {
+            jobValue.refresh();
+            jobValue.set("startDateTime", null);
+            jobValue.set("runByInstanceId", null);
+            jobValue.set("statusId", "SERVICE_PENDING");
+            jobValue.store();
+        } catch (GenericEntityException e) {
+            throw new InvalidJobException("Unable to dequeue job [" + getJobId() + "]", e);
+        }
+        if (Debug.verboseOn()) {
+            Debug.logVerbose("Job [" + getJobId() + "] not queued, rescheduling", module);
+        }
+    }
+
+    @Override
+    public Date getStartTime() {
+        return new Date(startTime);
+    }
 }

Modified: ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/rmi/RmiServiceContainer.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/rmi/RmiServiceContainer.java?rev=1401975&r1=1401974&r2=1401975&view=diff
==============================================================================
--- ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/rmi/RmiServiceContainer.java (original)
+++ ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/rmi/RmiServiceContainer.java Thu Oct 25 05:04:09 2012
@@ -48,9 +48,7 @@ public class RmiServiceContainer impleme
     private String containerName;
     // Container methods
 
-    /**
-     * @see org.ofbiz.base.container.Container#init(String[] args, String name, String configFile)
-     */
+    @Override
     public void init(String[] args, String name, String configFile) {
         this.containerName = name;
         this.configFile = configFile;

Modified: ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/Config.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/Config.java?rev=1401975&r1=1401974&r2=1401975&view=diff
==============================================================================
--- ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/Config.java (original)
+++ ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/Config.java Thu Oct 25 05:04:09 2012
@@ -73,7 +73,7 @@ public class Config {
     public String containerConfig;
     public String instrumenterClassName;
     public String instrumenterFile;
-    public List<Map> loaders;
+    public List<Map<String, String>> loaders;
     public String logDir;
     public String ofbizHome;
     public boolean requireCommJar = false;
@@ -420,7 +420,7 @@ public class Config {
         instrumenterFile = getProp(props, "ofbiz.instrumenterFile", null);
 
         // loader classes
-        loaders = new ArrayList<Map>();
+        loaders = new ArrayList<Map<String, String>>();
         int currentPosition = 1;
         Map<String, String> loader = null;
         while (true) {

Modified: ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/Start.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/Start.java?rev=1401975&r1=1401974&r2=1401975&view=diff
==============================================================================
--- ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/Start.java (original)
+++ ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/Start.java Thu Oct 25 05:04:09 2012
@@ -35,33 +35,29 @@ import java.util.Map;
 import java.util.concurrent.atomic.AtomicReference;
 
 /**
- * Start - OFBiz Container(s) Startup Class
- *
+ * OFBiz startup class.
+ * 
  */
-public class Start {
+public final class Start {
 
-    private enum Control {
-        SHUTDOWN {
-            void processRequest(Start start, PrintWriter writer) {
-                if (start.serverState.get() == ServerState.STOPPING) {
-                    writer.println("IN-PROGRESS");
-                } else {
-                    writer.println("OK");
-                    writer.flush();
-                    start.stopServer();
-                }
-            }
-        }, STATUS {
-            void processRequest(Start start, PrintWriter writer) {
-                writer.println(start.serverState.get());
-            }
-        }, FAIL {
-            void processRequest(Start start, PrintWriter writer) {
-                writer.println("FAIL");
-            }
-        };
+    private static final Start instance = new Start();
 
-        abstract void processRequest(Start start, PrintWriter writer);
+    private static Command checkCommand(Command command, Command wanted) {
+        if (wanted == Command.HELP || wanted.equals(command)) {
+            return wanted;
+        } else if (command == null) {
+            return wanted;
+        } else {
+            System.err.println("Duplicate command detected(was " + command + ", wanted " + wanted);
+            return Command.HELP_ERROR;
+        }
+    }
+
+    /**
+     * Returns the <code>Start</code> instance.
+     */
+    public static Start getInstance() {
+        return instance;
     }
 
     private static void help(PrintStream out) {
@@ -80,25 +76,10 @@ public class Start {
         out.println("[no command] -> Start the server w/ default config");
     }
 
-    private enum Command {
-        HELP, HELP_ERROR, STATUS, SHUTDOWN, COMMAND
-    }
-
-    private static Command checkCommand(Command command, Command wanted) {
-        if (wanted == Command.HELP || wanted.equals(command)) {
-            return wanted;
-        } else if (command == null) {
-            return wanted;
-        } else {
-            System.err.println("Duplicate command detected(was " + command + ", wanted " + wanted);
-            return Command.HELP_ERROR;
-        }
-    }
-
     public static void main(String[] args) throws StartupException {
         Command command = null;
         List<String> loaderArgs = new ArrayList<String>(args.length);
-        for (String arg: args) {
+        for (String arg : args) {
             if (arg.equals("-help") || arg.equals("-?")) {
                 command = checkCommand(command, Command.HELP);
             } else if (arg.equals("-status")) {
@@ -128,16 +109,15 @@ public class Start {
             help(System.err);
             System.exit(1);
         }
-        Start start = new Start();
-        start.init(args, command == Command.COMMAND);
+        instance.init(args, command == Command.COMMAND);
         try {
             if (command == Command.STATUS) {
-                System.out.println("Current Status : " + start.status());
+                System.out.println("Current Status : " + instance.status());
             } else if (command == Command.SHUTDOWN) {
-                System.out.println("Shutting down server : " + start.shutdown());
+                System.out.println("Shutting down server : " + instance.shutdown());
             } else {
                 // general start
-                start.start();
+                instance.start();
             }
         } catch (Exception e) {
             e.printStackTrace();
@@ -145,20 +125,16 @@ public class Start {
         }
     }
 
-    private enum ServerState {
-        STARTING, RUNNING, STOPPING;
-
-        public String toString() {
-            return name().charAt(0) + name().substring(1).toLowerCase();
-        }
-    }
+    // ---------------------------------------------- //
 
     private Config config = null;
-    private List<String> loaderArgs = new ArrayList<String>();
+    private final List<String> loaderArgs = new ArrayList<String>();
     private final ArrayList<StartupLoader> loaders = new ArrayList<StartupLoader>();
-    private AtomicReference<ServerState> serverState = new AtomicReference<ServerState>(ServerState.STARTING);
+    private final AtomicReference<ServerState> serverState = new AtomicReference<ServerState>(ServerState.STARTING);
     private Thread adminPortThread = null;
 
+    private Start() {}
+
     private void createListenerThread() throws StartupException {
         if (config.adminPort > 0) {
             this.adminPortThread = new AdminPortThread();
@@ -177,11 +153,14 @@ public class Start {
         }
     }
 
-    public void init(String[] args) throws StartupException {
-        init(args, true);
+    /**
+     * Returns the server's current state.
+     */
+    public ServerState getCurrentState() {
+        return serverState.get();
     }
 
-    public void init(String[] args, boolean fullInit) throws StartupException {
+    private void init(String[] args, boolean fullInit) throws StartupException {
         String globalSystemPropsFileName = System.getProperty("ofbiz.system.props");
         if (globalSystemPropsFileName != null) {
             FileInputStream stream = null;
@@ -191,7 +170,7 @@ public class Start {
             } catch (IOException e) {
                 throw (StartupException) new StartupException("Couldn't load global system props").initCause(e);
             } finally {
-                if (stream != null){
+                if (stream != null) {
                     try {
                         stream.close();
                     } catch (IOException e) {
@@ -209,22 +188,22 @@ public class Start {
         if (args.length > 1) {
             this.loaderArgs.addAll(Arrays.asList(args).subList(1, args.length));
         }
-
         if (!fullInit) {
             return;
         }
         // initialize the classpath
         initClasspath();
-
         // create the log directory
         createLogDirectory();
-
         // create the listener thread
         createListenerThread();
-
         // set the shutdown hook
         if (config.useShutdownHook) {
-            Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { shutdownServer(); } });
+            Runtime.getRuntime().addShutdownHook(new Thread() {
+                public void run() {
+                    shutdownServer();
+                }
+            });
         } else {
             System.out.println("Shutdown hook disabled");
         }
@@ -254,12 +233,12 @@ public class Start {
         ClassLoader classloader = Thread.currentThread().getContextClassLoader();
         synchronized (this.loaders) {
             // initialize the loaders
-            for (Map loaderMap: config.loaders) {
+            for (Map<String, String> loaderMap : config.loaders) {
                 if (this.serverState.get() == ServerState.STOPPING) {
                     return;
                 }
                 try {
-                    String loaderClassName = (String)loaderMap.get("class");
+                    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()]));
@@ -279,24 +258,19 @@ public class Start {
 
     private String sendSocketCommand(Control control) throws IOException, ConnectException {
         String response = "OFBiz is Down";
-
         try {
-        Socket socket = new Socket(config.adminAddress, config.adminPort);
-
-        // send the command
-        PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
-        writer.println(config.adminKey + ":" + control);
-        writer.flush();
-
-        // read the reply
-        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
-        response = reader.readLine();
-
-        reader.close();
-
-        // close the socket
-        writer.close();
-        socket.close();
+            Socket socket = new Socket(config.adminAddress, config.adminPort);
+            // send the command
+            PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
+            writer.println(config.adminKey + ":" + control);
+            writer.flush();
+            // read the reply
+            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+            response = reader.readLine();
+            reader.close();
+            // close the socket
+            writer.close();
+            socket.close();
 
         } catch (ConnectException e) {
             System.out.println("Could not connect to " + config.adminAddress + ":" + config.adminPort);
@@ -304,7 +278,7 @@ public class Start {
         return response;
     }
 
-    public String shutdown() throws IOException {
+    private String shutdown() throws IOException {
         return sendSocketCommand(Control.SHUTDOWN);
     }
 
@@ -334,20 +308,6 @@ public class Start {
         }
     }
 
-    // org.apache.commons.daemon.Daemon.start()
-    public void start() throws Exception {
-        if (!startStartLoaders()) {
-            if (this.serverState.get() == ServerState.STOPPING) {
-                return;
-            } else {
-                throw new Exception("Error during start.");
-            }
-        }
-        if (config.shutdownAfterLoad) {
-            stopServer();
-        }
-    }
-
     /**
      * Returns <code>true</code> if all loaders were started.
      * 
@@ -356,7 +316,7 @@ public class Start {
     private boolean startStartLoaders() {
         synchronized (this.loaders) {
             // start the loaders
-            for (StartupLoader loader: this.loaders) {
+            for (StartupLoader loader : this.loaders) {
                 if (this.serverState.get() == ServerState.STOPPING) {
                     return false;
                 }
@@ -371,7 +331,7 @@ public class Start {
         return this.serverState.compareAndSet(ServerState.STARTING, ServerState.RUNNING);
     }
 
-    public String status() throws IOException {
+    private String status() throws IOException {
         try {
             return sendSocketCommand(Control.STATUS);
         } catch (ConnectException e) {
@@ -381,21 +341,41 @@ public class Start {
         }
     }
 
-    public void stopServer() {
+    private void stopServer() {
         shutdownServer();
         System.exit(0);
     }
 
+    // ----------------------------------------------- //
+    // org.apache.commons.daemon.Daemon implementation //
+    // ----------------------------------------------- //
+
     // org.apache.commons.daemon.Daemon.destroy()
     public void destroy() {
         // FIXME: undo init() calls.
     }
 
+    // org.apache.commons.daemon.Daemon.start()
+    public void start() throws Exception {
+        if (!startStartLoaders()) {
+            if (this.serverState.get() == ServerState.STOPPING) {
+                return;
+            } else {
+                throw new Exception("Error during start.");
+            }
+        }
+        if (config.shutdownAfterLoad) {
+            stopServer();
+        }
+    }
+
     // org.apache.commons.daemon.Daemon.stop()
     public void stop() {
         shutdownServer();
     }
 
+    // ----------------------------------------------- //
+
     private class AdminPortThread extends Thread {
         private ServerSocket serverSocket = null;
 
@@ -457,4 +437,42 @@ public class Start {
             }
         }
     }
+
+    private enum Command {
+        HELP, HELP_ERROR, STATUS, SHUTDOWN, COMMAND
+    }
+
+    private enum Control {
+        SHUTDOWN {
+            void processRequest(Start start, PrintWriter writer) {
+                if (start.serverState.get() == ServerState.STOPPING) {
+                    writer.println("IN-PROGRESS");
+                } else {
+                    writer.println("OK");
+                    writer.flush();
+                    start.stopServer();
+                }
+            }
+        },
+        STATUS {
+            void processRequest(Start start, PrintWriter writer) {
+                writer.println(start.serverState.get());
+            }
+        },
+        FAIL {
+            void processRequest(Start start, PrintWriter writer) {
+                writer.println("FAIL");
+            }
+        };
+
+        abstract void processRequest(Start start, PrintWriter writer);
+    }
+
+    public enum ServerState {
+        STARTING, RUNNING, STOPPING;
+
+        public String toString() {
+            return name().charAt(0) + name().substring(1).toLowerCase();
+        }
+    }
 }

Modified: ofbiz/branches/20120329_portletWidget/framework/testtools/src/org/ofbiz/testtools/TestListContainer.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/testtools/src/org/ofbiz/testtools/TestListContainer.java?rev=1401975&r1=1401974&r2=1401975&view=diff
==============================================================================
--- ofbiz/branches/20120329_portletWidget/framework/testtools/src/org/ofbiz/testtools/TestListContainer.java (original)
+++ ofbiz/branches/20120329_portletWidget/framework/testtools/src/org/ofbiz/testtools/TestListContainer.java Thu Oct 25 05:04:09 2012
@@ -58,9 +58,7 @@ public class TestListContainer implement
         }
     }
 
-    /**
-     * @see org.ofbiz.base.container.Container#init(String[] args, String name, String configFile)
-     */
+    @Override
     public void init(String[] args, String name, String configFile) {
         this.name = name;
         this.outputLocation = args[0];
@@ -105,8 +103,7 @@ public class TestListContainer implement
                     pout.format("%s:%s", foundTest.componentName, foundTest.suiteName);
                 }
                 pout.println("\"/>\n");
-                for (int i = 0; i < foundTests.size(); i++) {
-                    FoundTest foundTest = foundTests.get(i);
+                for (FoundTest foundTest : foundTests) {
                     pout.format(" <target name=\"%1$s:%2$s\">\n  <ant antfile=\"build.xml\" target=\"run-single-test-suite\">\n   <property name=\"test.component\" value=\"%1$s\"/>\n   <property name=\"test.suiteName\" value=\"%2$s\"/>\n  </ant>\n </target>\n", foundTest.componentName, foundTest.suiteName);
                 }
                 pout.println("</project>");

Modified: ofbiz/branches/20120329_portletWidget/framework/testtools/src/org/ofbiz/testtools/TestRunContainer.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/testtools/src/org/ofbiz/testtools/TestRunContainer.java?rev=1401975&r1=1401974&r2=1401975&view=diff
==============================================================================
--- ofbiz/branches/20120329_portletWidget/framework/testtools/src/org/ofbiz/testtools/TestRunContainer.java (original)
+++ ofbiz/branches/20120329_portletWidget/framework/testtools/src/org/ofbiz/testtools/TestRunContainer.java Thu Oct 25 05:04:09 2012
@@ -59,15 +59,12 @@ public class TestRunContainer implements
 
     private String name;
 
-    /**
-     * @see org.ofbiz.base.container.Container#init(String[] args, String name, String configFile)
-     */
+    @Override
     public void init(String[] args, String name, String configFile) {
         this.name = name;
         this.configFile = configFile;
         if (args != null) {
-            for (int i = 0; i < args.length; i++) {
-                String argument = args[i];
+            for (String argument : args) {
                 // arguments can prefix w/ a '-'. Just strip them off
                 if (argument.startsWith("-")) {
                     int subIdx = 1;

Modified: ofbiz/branches/20120329_portletWidget/framework/webapp/src/org/ofbiz/webapp/control/ContextFilter.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/webapp/src/org/ofbiz/webapp/control/ContextFilter.java?rev=1401975&r1=1401974&r2=1401975&view=diff
==============================================================================
--- ofbiz/branches/20120329_portletWidget/framework/webapp/src/org/ofbiz/webapp/control/ContextFilter.java (original)
+++ ofbiz/branches/20120329_portletWidget/framework/webapp/src/org/ofbiz/webapp/control/ContextFilter.java Thu Oct 25 05:04:09 2012
@@ -60,6 +60,7 @@ import org.ofbiz.security.SecurityConfig
 import org.ofbiz.security.SecurityFactory;
 import org.ofbiz.service.LocalDispatcher;
 import org.ofbiz.service.ServiceContainer;
+import org.ofbiz.webapp.website.WebSiteWorker;
 
 /**
  * ContextFilter - Restricts access to raw files and configures servlet objects.
@@ -126,7 +127,7 @@ public class ContextFilter implements Fi
 
         // set the webSiteId in the session
         if (UtilValidate.isEmpty(httpRequest.getSession().getAttribute("webSiteId"))){
-            httpRequest.getSession().setAttribute("webSiteId", config.getServletContext().getAttribute("webSiteId"));
+            httpRequest.getSession().setAttribute("webSiteId", WebSiteWorker.getWebSiteId(httpRequest));
         }
 
         // set the filesystem path of context root.

Modified: ofbiz/branches/20120329_portletWidget/framework/webapp/src/org/ofbiz/webapp/control/ControlServlet.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/webapp/src/org/ofbiz/webapp/control/ControlServlet.java?rev=1401975&r1=1401974&r2=1401975&view=diff
==============================================================================
--- ofbiz/branches/20120329_portletWidget/framework/webapp/src/org/ofbiz/webapp/control/ControlServlet.java (original)
+++ ofbiz/branches/20120329_portletWidget/framework/webapp/src/org/ofbiz/webapp/control/ControlServlet.java Thu Oct 25 05:04:09 2012
@@ -225,6 +225,9 @@ public class ControlServlet extends Http
                 request.setAttribute("_ERROR_MESSAGE_", encoder.encode(throwable.toString()));
                 errorPage = requestHandler.getDefaultErrorPage(request);
             }
+         } catch (RequestHandlerExceptionAllowExternalRequests e) {
+              errorPage = requestHandler.getDefaultErrorPage(request);
+              Debug.logInfo("Going to external page: " + request.getPathInfo(), module);
         } catch (Exception e) {
             Debug.logError(e, "Error in request handler: ", module);
             StringUtil.HtmlEncoder encoder = new StringUtil.HtmlEncoder();

Modified: ofbiz/branches/20120329_portletWidget/framework/webapp/src/org/ofbiz/webapp/control/LoginWorker.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/webapp/src/org/ofbiz/webapp/control/LoginWorker.java?rev=1401975&r1=1401974&r2=1401975&view=diff
==============================================================================
--- ofbiz/branches/20120329_portletWidget/framework/webapp/src/org/ofbiz/webapp/control/LoginWorker.java (original)
+++ ofbiz/branches/20120329_portletWidget/framework/webapp/src/org/ofbiz/webapp/control/LoginWorker.java Thu Oct 25 05:04:09 2012
@@ -981,7 +981,13 @@ public class LoginWorker {
         if (security != null) {
             ServletContext context = (ServletContext) request.getAttribute("servletContext");
             String serverId = (String) context.getAttribute("_serverId");
+            
+            // get a context path from the request, if it is empty then assume it is the root mount point
             String contextPath = request.getContextPath();
+            if (UtilValidate.isEmpty(contextPath)) {
+                contextPath = "/";
+            }
+            
             ComponentConfig.WebappInfo info = ComponentConfig.getWebAppInfo(serverId, contextPath);
             if (info != null) {
                 for (String permission: info.getBasePermission()) {

Modified: ofbiz/branches/20120329_portletWidget/framework/webapp/src/org/ofbiz/webapp/control/RequestHandler.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/webapp/src/org/ofbiz/webapp/control/RequestHandler.java?rev=1401975&r1=1401974&r2=1401975&view=diff
==============================================================================
--- ofbiz/branches/20120329_portletWidget/framework/webapp/src/org/ofbiz/webapp/control/RequestHandler.java (original)
+++ ofbiz/branches/20120329_portletWidget/framework/webapp/src/org/ofbiz/webapp/control/RequestHandler.java Thu Oct 25 05:04:09 2012
@@ -58,6 +58,7 @@ import org.ofbiz.webapp.view.ViewFactory
 import org.ofbiz.webapp.view.ViewHandler;
 import org.ofbiz.webapp.view.ViewHandlerException;
 import org.ofbiz.webapp.website.WebSiteWorker;
+import org.owasp.esapi.errors.EncodingException;
 
 /**
  * RequestHandler - Request Processor Object
@@ -65,6 +66,8 @@ import org.ofbiz.webapp.website.WebSiteW
 public class RequestHandler {
 
     public static final String module = RequestHandler.class.getName();
+    private static final Boolean THROW_REQUEST_HANDLER_EXCEPTION_ON_MISSING_LOCAL_REQUEST =  
+        UtilProperties.propertyValueEqualsIgnoreCase("requestHandler.properties", "throwRequestHandlerExceptionOnMissingLocalRequest", "Y");  
 
     public static RequestHandler getRequestHandler(ServletContext servletContext) {
         RequestHandler rh = (RequestHandler) servletContext.getAttribute("_REQUEST_HANDLER_");
@@ -96,7 +99,7 @@ public class RequestHandler {
         return ConfigXMLReader.getControllerConfig(this.controllerConfigURL);
     }
 
-    public void doRequest(HttpServletRequest request, HttpServletResponse response, String requestUri) throws RequestHandlerException {
+    public void doRequest(HttpServletRequest request, HttpServletResponse response, String requestUri) throws RequestHandlerException, RequestHandlerExceptionAllowExternalRequests {
         HttpSession session = request.getSession();
         Delegator delegator = (Delegator) request.getAttribute("delegator");
         GenericValue userLogin = (GenericValue) session.getAttribute("userLogin");
@@ -104,7 +107,7 @@ public class RequestHandler {
     }
 
     public void doRequest(HttpServletRequest request, HttpServletResponse response, String chain,
-            GenericValue userLogin, Delegator delegator) throws RequestHandlerException {
+            GenericValue userLogin, Delegator delegator) throws RequestHandlerException, RequestHandlerExceptionAllowExternalRequests {
 
         long startTime = System.currentTimeMillis();
         HttpSession session = request.getSession();
@@ -152,10 +155,13 @@ public class RequestHandler {
             }
         }
 
-        // still not found so stop
+        // if no matching request is found in the controller, depending on THROW_REQUEST_HANDLER_EXCEPTION_ON_MISSING_LOCAL_REQUEST
+        //  we throw a RequestHandlerException or RequestHandlerExceptionAllowExternalRequests
         if (requestMap == null) {
-            throw new RequestHandlerException(requestMissingErrorMessage);
-        }
+            if (THROW_REQUEST_HANDLER_EXCEPTION_ON_MISSING_LOCAL_REQUEST) throw new RequestHandlerException(requestMissingErrorMessage);
+            else throw new RequestHandlerExceptionAllowExternalRequests();
+         }
+
         String eventReturn = null;
         if (requestMap.metrics != null && requestMap.metrics.getThreshold() != 0.0 && requestMap.metrics.getTotalEvents() > 3 && requestMap.metrics.getThreshold() < requestMap.metrics.getServiceRate()) {
             eventReturn = "threshold-exceeded";
@@ -962,32 +968,36 @@ public class RequestHandler {
                     value = request.getParameter(from);
                 }
 
-                if (UtilValidate.isNotEmpty(value)) {
-                    if (queryString.length() > 1) {
-                        queryString.append("&");
-                    }
-                    queryString.append(name);
-                    queryString.append("=");
-                    queryString.append(value);
-                }
+                addNameValuePairToQueryString(queryString, name, (String) value);
             }
+
             for (Map.Entry<String, String> entry: requestResponse.redirectParameterValueMap.entrySet()) {
                 String name = entry.getKey();
                 String value = entry.getValue();
 
-                if (UtilValidate.isNotEmpty(value)) {
-                    if (queryString.length() > 1) {
-                        queryString.append("&");
-                    }
-                    queryString.append(name);
-                    queryString.append("=");
-                    queryString.append(value);
-                }
+                addNameValuePairToQueryString(queryString, name, value);
             }
+
             return queryString.toString();
         }
     }
 
+    private void addNameValuePairToQueryString(StringBuilder queryString, String name, String value) {
+        if (UtilValidate.isNotEmpty(value)) {
+            if (queryString.length() > 1) {
+                queryString.append("&");
+            }
+
+            try {
+                queryString.append(StringUtil.defaultWebEncoder.encodeForURL(name));
+                queryString.append("=");
+                queryString.append(StringUtil.defaultWebEncoder.encodeForURL(value));
+            } catch (EncodingException e) {
+                Debug.logError(e, module);
+            }
+        }
+    }
+
     public String makeLinkWithQueryString(HttpServletRequest request, HttpServletResponse response, String url, ConfigXMLReader.RequestResponse requestResponse) {
         String initialLink = this.makeLink(request, response, url);
         String queryString = this.makeQueryString(request, requestResponse);
@@ -1127,8 +1137,11 @@ public class RequestHandler {
                         newURL.insert(questionIndex, sessionId);
                     }
                 }
-
-                encodedUrl = newURL.toString();
+                if (response != null) {
+                    encodedUrl = response.encodeURL(newURL.toString());
+                } else {
+                    encodedUrl = newURL.toString();
+                }
             }
         } else {
             encodedUrl = newURL.toString();

Modified: ofbiz/branches/20120329_portletWidget/framework/webtools/config/WebtoolsUiLabels.xml
URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/webtools/config/WebtoolsUiLabels.xml?rev=1401975&r1=1401974&r2=1401975&view=diff
==============================================================================
--- ofbiz/branches/20120329_portletWidget/framework/webtools/config/WebtoolsUiLabels.xml (original)
+++ ofbiz/branches/20120329_portletWidget/framework/webtools/config/WebtoolsUiLabels.xml Thu Oct 25 05:04:09 2012
@@ -920,8 +920,8 @@
     </property>
     <property key="WebtoolsCheckAll">
         <value xml:lang="de">Alle auswählen</value>
-        <value xml:lang="en">Check All</value>
-        <value xml:lang="fr">Tout sélectionner</value>
+        <value xml:lang="en">Check All (not views)</value>
+        <value xml:lang="fr">Tout sélectionner (pas les views)</value>
         <value xml:lang="it">Seleziona tutto</value>
         <value xml:lang="pt">Selecionar todos</value>
         <value xml:lang="th">ตรวจสอบทั้งหมด</value>
@@ -4181,7 +4181,7 @@
     </property>
     <property key="WebtoolsServiceEngineThreads">
         <value xml:lang="de">Dienste-Engine Threads</value>
-        <value xml:lang="en">Service Engine Threads</value>
+        <value xml:lang="en">Job Queue Service Threads</value>
         <value xml:lang="fr">Threads du Service Engine</value>
         <value xml:lang="it">Threads dell' Engine Servizi</value>
         <value xml:lang="pt">Threads do Engine de serviços</value>

Modified: ofbiz/branches/20120329_portletWidget/framework/webtools/webapp/webtools/WEB-INF/actions/entity/FindGeneric.groovy
URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/webtools/webapp/webtools/WEB-INF/actions/entity/FindGeneric.groovy?rev=1401975&r1=1401974&r2=1401975&view=diff
==============================================================================
--- ofbiz/branches/20120329_portletWidget/framework/webtools/webapp/webtools/WEB-INF/actions/entity/FindGeneric.groovy (original)
+++ ofbiz/branches/20120329_portletWidget/framework/webtools/webapp/webtools/WEB-INF/actions/entity/FindGeneric.groovy Thu Oct 25 05:04:09 2012
@@ -174,8 +174,13 @@ if ("true".equals(find)) {
                     fieldsToSelect.add(functionField)
                 }
             }
-
-            resultEli = delegator.find(entityName, condition, null, fieldsToSelect, null, efo);
+            Collection pkNames = FastList.newInstance();
+            Iterator iter = modelEntity.getPksIterator();
+            while (iter != null && iter.hasNext()) {
+                ModelField curField = (ModelField) iter.next();
+                pkNames.add(curField.getName());
+            }
+            resultEli = delegator.find(entityName, condition, null, fieldsToSelect, pkNames, efo);
             resultPartialList = resultEli.getPartialList(lowIndex, highIndex - lowIndex + 1);
 
             arraySize = resultEli.getResultsSizeAfterPartialList();

Modified: ofbiz/branches/20120329_portletWidget/framework/webtools/webapp/webtools/entity/xmldsdump.ftl
URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/webtools/webapp/webtools/entity/xmldsdump.ftl?rev=1401975&r1=1401974&r2=1401975&view=diff
==============================================================================
--- ofbiz/branches/20120329_portletWidget/framework/webtools/webapp/webtools/entity/xmldsdump.ftl (original)
+++ ofbiz/branches/20120329_portletWidget/framework/webtools/webapp/webtools/entity/xmldsdump.ftl Thu Oct 25 05:04:09 2012
@@ -41,10 +41,10 @@ under the License.
 
 <#if security.hasPermission("ENTITY_MAINT", session)>
   <h2>${uiLabelMap.WebtoolsResults}:</h2>
-  <#if Static["org.ofbiz.base.util.UtilValidate"].isNotEmpty(parameters.filename) && (numberOfEntities?number > 0)>
+  <#if parameters.filename?has_content && (numberOfEntities?number > 0)>
     <p>${uiLabelMap.WebtoolsWroteXMLForAllDataIn}</p>
     <p>${uiLabelMap.WebtoolsWroteNRecordsToXMLFile}</p>
-  <#elseif Static["org.ofbiz.base.util.UtilValidate"].isNotEmpty(parameters.outpath) && (numberOfEntities?number > 0)>
+  <#elseif parameters.outpath?has_content && (numberOfEntities?number > 0)>
     <#list results as result>
       <p>${result}</p>
     </#list>

Modified: ofbiz/branches/20120329_portletWidget/framework/webtools/widget/ServiceForms.xml
URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/webtools/widget/ServiceForms.xml?rev=1401975&r1=1401974&r2=1401975&view=diff
==============================================================================
--- ofbiz/branches/20120329_portletWidget/framework/webtools/widget/ServiceForms.xml (original)
+++ ofbiz/branches/20120329_portletWidget/framework/webtools/widget/ServiceForms.xml Thu Oct 25 05:04:09 2012
@@ -96,7 +96,7 @@ under the License.
             </hyperlink>
         </field>
         <field name="statusId" title="${uiLabelMap.CommonStatus}" sort-field="true"><display-entity entity-name="StatusItem" description="${description}"/></field>
-        <field name="cancelDateTime" title="${uiLabelMap.CommonEndDateTime}" sort-field="true"><display/></field>
+        <field name="finishDateTime" title="${uiLabelMap.CommonEndDateTime}" sort-field="true"><display/></field>
         <field name="cancelButton" title=" " use-when="startDateTime==null&amp;&amp;finishDateTime==null&amp;&amp;cancelDateTime==null" widget-style="buttontext">
             <hyperlink also-hidden="false" description="${uiLabelMap.WebtoolsCancelJob}" target="cancelJob">
                 <parameter param-name="jobId"/>
@@ -111,9 +111,6 @@ under the License.
         <field name="value"><display/></field>
     </form>
     <form name="PoolState" type="single" default-map-name="poolState">
-        <field name="pollerName"><display/></field>
-        <field name="pollerThreadName"><display/></field>
-        <field name="invokerThreadNameFormat"><display/></field>
         <field name="keepAliveTimeInSeconds"><display/></field>
         <field name="numberOfCoreInvokerThreads"><display/></field>
         <field name="currentNumberOfInvokerThreads"><display/></field>
@@ -127,7 +124,7 @@ under the License.
         <field name="id" title="${uiLabelMap.WebtoolsThread}"><display description="${threadId} ${threadName}"/></field>
         <field name="name" title="${uiLabelMap.WebtoolsJob}"><display default-value="${uiLabelMap.CommonNone}"/></field>
         <field name="serviceName" title="${uiLabelMap.WebtoolsService}"><display default-value="${uiLabelMap.CommonNone}"/></field>
-        <field name="time"><display/></field>
+        <field name="time" title="${uiLabelMap.CommonStartDateTime}"><display/></field>
         <field name="runTime" title="${uiLabelMap.CommonTime} (ms)"><display/></field>
     </form>
     <form name="ListServices" type="list" list-name="services" paginate-target="ServiceLog" separate-columns="true"

Modified: ofbiz/branches/20120329_portletWidget/framework/widget/src/org/ofbiz/widget/WidgetWorker.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/widget/src/org/ofbiz/widget/WidgetWorker.java?rev=1401975&r1=1401974&r2=1401975&view=diff
==============================================================================
--- ofbiz/branches/20120329_portletWidget/framework/widget/src/org/ofbiz/widget/WidgetWorker.java (original)
+++ ofbiz/branches/20120329_portletWidget/framework/widget/src/org/ofbiz/widget/WidgetWorker.java Thu Oct 25 05:04:09 2012
@@ -292,10 +292,15 @@ public class WidgetWorker {
 
         for (Map.Entry<String, String> parameter: parameterMap.entrySet()) {
             if (parameter.getValue() != null) {
+                String key = parameter.getKey();
+
                 writer.append("<input name=\"");
-                writer.append(parameter.getKey());
+                writer.append(key);
                 writer.append("\" value=\"");
-                writer.append(parameter.getValue());
+
+                String valueFromContext = context.containsKey(key) ?
+                        context.get(key).toString() : parameter.getValue();
+                writer.append(valueFromContext);
                 writer.append("\" type=\"hidden\"/>");
             }
         }

Modified: ofbiz/branches/20120329_portletWidget/framework/widget/src/org/ofbiz/widget/form/ModelFormField.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/widget/src/org/ofbiz/widget/form/ModelFormField.java?rev=1401975&r1=1401974&r2=1401975&view=diff
==============================================================================
--- ofbiz/branches/20120329_portletWidget/framework/widget/src/org/ofbiz/widget/form/ModelFormField.java (original)
+++ ofbiz/branches/20120329_portletWidget/framework/widget/src/org/ofbiz/widget/form/ModelFormField.java Thu Oct 25 05:04:09 2012
@@ -983,10 +983,15 @@ public class ModelFormField {
     }
 
     public String getTooltip(Map<String, Object> context) {
-        if (UtilValidate.isNotEmpty(tooltip)) return tooltip.expandString(context);
-        return "";
+        String tooltipString = "";
+        if (UtilValidate.isNotEmpty(tooltip)) tooltipString = tooltip.expandString(context);
+        if (this.getEncodeOutput()) {            
+            StringUtil.SimpleEncoder simpleEncoder = (StringUtil.SimpleEncoder) context.get("simpleEncoder");
+            if (simpleEncoder != null) tooltipString = simpleEncoder.encode(tooltipString);
+        }
+        return tooltipString;        
     }
-
+    
     public String getUseWhen(Map<String, Object> context) {
         if (UtilValidate.isNotEmpty(this.useWhen)) return this.useWhen.expandString(context);
         return "";
@@ -1996,7 +2001,6 @@ public class ModelFormField {
 
         public String getDescription(Map<String, Object> context) {
             String retVal = null;
-            // Don't replace by UtilValidate.isNotEmpty: this.description is a FlexibleStringExpander and issues occur
             if (UtilValidate.isNotEmpty(this.description)) retVal = this.description.expandString(context);
             else retVal = this.modelFormField.getEntry(context);
 
@@ -2079,7 +2083,6 @@ public class ModelFormField {
                     throw new IllegalArgumentException(errMsg);
                 }
             }
-         // Don't replace by UtilValidate.isNotEmpty: this.description is a FlexibleStringExpander and issues occur
             if (UtilValidate.isNotEmpty(this.description) && retVal != null && this.getModelFormField().getEncodeOutput()) {
                 StringUtil.SimpleEncoder simpleEncoder = (StringUtil.SimpleEncoder) context.get("simpleEncoder");
                 if (simpleEncoder != null) {
@@ -2175,10 +2178,7 @@ public class ModelFormField {
             this.cache = !"false".equals(element.getAttribute("cache"));
             this.size = element.getAttribute("size");
 
-         // Don't replace by UtilValidate.isNotEmpty: this.description is a FlexibleStringExpander and issues occur
-            if (this.description == null || this.description.isEmpty()) {
-                this.setDescription("${description}");
-            }
+            if (UtilValidate.isEmpty(this.description))  this.setDescription("${description}");
 
             Element subHyperlinkElement = UtilXml.firstChildElement(element, "sub-hyperlink");
             if (subHyperlinkElement != null) {
@@ -4125,7 +4125,6 @@ public class ModelFormField {
         }
 
         public String getDescription(Map<String, Object> context) {
-         // Don't replace by UtilValidate.isNotEmpty: this.description is a FlexibleStringExpander and issues occur
             if (UtilValidate.isNotEmpty(this.description)) return this.description.expandString(context);
             return "";
         }

Modified: ofbiz/branches/20120329_portletWidget/framework/widget/src/org/ofbiz/widget/screen/ScreenRenderer.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/widget/src/org/ofbiz/widget/screen/ScreenRenderer.java?rev=1401975&r1=1401974&r2=1401975&view=diff
==============================================================================
--- ofbiz/branches/20120329_portletWidget/framework/widget/src/org/ofbiz/widget/screen/ScreenRenderer.java (original)
+++ ofbiz/branches/20120329_portletWidget/framework/widget/src/org/ofbiz/widget/screen/ScreenRenderer.java Thu Oct 25 05:04:09 2012
@@ -53,6 +53,7 @@ import org.ofbiz.service.DispatchContext
 import org.ofbiz.service.GenericServiceException;
 import org.ofbiz.service.LocalDispatcher;
 import org.ofbiz.webapp.control.LoginWorker;
+import org.ofbiz.webapp.website.WebSiteWorker;
 import org.ofbiz.widget.cache.GenericWidgetOutput;
 import org.ofbiz.widget.cache.ScreenCache;
 import org.ofbiz.widget.cache.WidgetContextCacheKey;
@@ -225,7 +226,7 @@ public class ScreenRenderer {
                 context.put("rootDir", rootDir);
             }
             if (UtilValidate.isEmpty(webSiteId)) {
-                webSiteId = (String) servletContext.getAttribute("webSiteId");
+                webSiteId = WebSiteWorker.getWebSiteId(request);
                 context.put("webSiteId", webSiteId);
             }
             if (UtilValidate.isEmpty(https)) {

Modified: ofbiz/branches/20120329_portletWidget/framework/widget/src/org/ofbiz/widget/tree/ModelTree.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/widget/src/org/ofbiz/widget/tree/ModelTree.java?rev=1401975&r1=1401974&r2=1401975&view=diff
==============================================================================
--- ofbiz/branches/20120329_portletWidget/framework/widget/src/org/ofbiz/widget/tree/ModelTree.java (original)
+++ ofbiz/branches/20120329_portletWidget/framework/widget/src/org/ofbiz/widget/tree/ModelTree.java Thu Oct 25 05:04:09 2012
@@ -664,7 +664,13 @@ public class ModelTree extends ModelWidg
                     ModelField modelField = modelEntity.getOnlyPk();
                     this.pkName = modelField.getName();
                 } else {
-                    // TODO: what to do here?
+                    List<String> pkFieldsName = modelEntity.getPkFieldNames();
+                    StringBuilder sb = new StringBuilder();
+                    for (String pk: pkFieldsName) {
+                            sb.append(pk);
+                            sb.append("|");
+                    }
+                    this.pkName = sb.toString();
                 }
             }
         }