You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@batchee.apache.org by rm...@apache.org on 2013/11/05 08:38:40 UTC

[03/62] Importing JBatch Reference Implementation from IBM. We'll fork it but this commit is to keep a track of what we forked.

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/f7740962/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/JSEBatchArtifactFactoryImpl.java
----------------------------------------------------------------------
diff --git a/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/JSEBatchArtifactFactoryImpl.java b/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/JSEBatchArtifactFactoryImpl.java
new file mode 100755
index 0000000..bbd5757
--- /dev/null
+++ b/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/JSEBatchArtifactFactoryImpl.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2012 International Business Machines Corp.
+ * 
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. Licensed under the Apache License, 
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+package com.ibm.jbatch.container.services.impl;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamReader;
+
+import com.ibm.jbatch.container.exception.BatchContainerRuntimeException;
+import com.ibm.jbatch.container.exception.BatchContainerServiceException;
+import com.ibm.jbatch.spi.services.IBatchArtifactFactory;
+import com.ibm.jbatch.spi.services.IBatchConfig;
+
+public class JSEBatchArtifactFactoryImpl implements IBatchArtifactFactory, XMLStreamConstants {
+
+	private final static Logger logger = Logger.getLogger(JSEBatchArtifactFactoryImpl.class.getName());
+	private final static String CLASSNAME = JSEBatchArtifactFactoryImpl.class.getName();
+
+	// TODO - surface constants
+	private final static String BATCH_XML = "META-INF/batch.xml";
+	private final static QName BATCH_ROOT_ELEM = new QName("http://xmlns.jcp.org/xml/ns/javaee", "batch-artifacts");
+
+	// TODO - synchronize appropriately once we learn more about usage
+	private boolean loaded = false;
+	private volatile ArtifactMap artifactMap = null;
+
+	// Uses TCCL
+	@Override
+	public Object load(String batchId) {
+		String methodName = "load";
+
+		if (logger.isLoggable(Level.FINER)) {
+			logger.entering(CLASSNAME, methodName, "Loading batch artifact id = " + batchId);
+		}
+
+		ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+
+		if (logger.isLoggable(Level.FINE)) {
+			logger.fine("TCCL = " + tccl);
+		}
+
+		initArtifactMapFromClassLoader(tccl);
+
+		Object loadedArtifact = artifactMap.getArtifactById(batchId);
+
+		if (loadedArtifact == null) {
+			throw new IllegalArgumentException("Could not load any artifacts with batch id=" + batchId);
+		}
+
+		if (logger.isLoggable(Level.FINER)) {
+			logger.exiting(CLASSNAME, methodName, "For batch artifact id = " + batchId + ", loaded artifact instance: " +
+					loadedArtifact + " of type: " + loadedArtifact.getClass().getCanonicalName());
+		}
+		return loadedArtifact;
+	}
+
+	private void initArtifactMapFromClassLoader(ClassLoader loader) {
+		/*
+		 * Following pattern in:
+		 *   http://en.wikipedia.org/wiki/Double-checked_locking
+		 */
+		ArtifactMap tempMap = artifactMap;
+		if (tempMap == null) {
+			synchronized(this) {
+				tempMap = artifactMap;
+				if (tempMap == null) {
+					tempMap = new ArtifactMap();                    
+					InputStream is = getBatchXMLStreamFromClassLoader(loader);
+					artifactMap = populateArtifactMapFromStream(tempMap, is);					
+				}
+			}
+		}
+	}
+
+	protected InputStream getBatchXMLStreamFromClassLoader(ClassLoader loader) {
+		InputStream is = loader.getResourceAsStream(BATCH_XML);
+
+		if (is == null) {
+			throw new IllegalStateException("Unable to load batch.xml");
+		}
+
+		return is;
+	}
+
+	/*
+	 * Non-validating (e.g. that the artifact type is correct) load
+	 * 
+	 * TODO - add some logging to the parsing
+	 */
+	protected ArtifactMap populateArtifactMapFromStream(ArtifactMap tempMap, InputStream is) {
+		XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
+
+
+		try {
+			XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(is);
+
+			if (logger.isLoggable(Level.FINEST)) {
+				logger.finest("Loaded XMLStreamReader = " + xmlStreamReader);
+			}
+
+			boolean processedRoot = false;
+
+			// We are going to take advantage of the simplified structure of a
+			// line
+			// E.g.:
+			// <batch-artifacts>
+			//   <ref id="myItemProcessor" class="jsr352/sample/MyItemProcessorImpl" />
+			//   ..
+			// </batch-artifacts>
+			//
+			// and have much simpler logic than general-purpose parsing would
+			// require.
+			while (xmlStreamReader.hasNext()) {
+				int event = xmlStreamReader.next();
+
+				// Until we reach end of document
+				if (event == END_DOCUMENT) {
+					break;
+				}
+
+				// At this point we have either:
+				//    A) just passed START_DOCUMENT, and are at START_ELEMENT for the root, 
+				//       <batch-artifacts>, or 
+				//    B) we have just passed END_ELEMENT for one of the artifacts which is a child of
+				//       <batch-artifacts>.
+				//   
+				//  Only handle START_ELEMENT now so we can skip whitespace CHARACTERS events.
+				//
+				if (event == START_ELEMENT) {
+					if (!processedRoot) {
+						QName rootQName = xmlStreamReader.getName();
+						if (!rootQName.equals(BATCH_ROOT_ELEM)) {
+							throw new IllegalStateException("Expecting document with root element QName: " + BATCH_ROOT_ELEM
+									+ ", but found root element with QName: " + rootQName);
+						} else {
+							processedRoot = true;
+						}
+					} else {
+
+						// Should only need localName
+						String annotationShortName = xmlStreamReader.getLocalName();
+						String id = xmlStreamReader.getAttributeValue(null, "id");
+						String className = xmlStreamReader.getAttributeValue(null, "class");
+						tempMap.addEntry(annotationShortName, id, className);
+
+						// Ignore anything else (text/whitespace) within this
+						// element
+						while (event != END_ELEMENT) {
+							event = xmlStreamReader.next();
+						}
+					}
+				}
+			}
+			xmlStreamReader.close();
+			is.close();
+			return tempMap;
+
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	private class ArtifactMap {
+
+		private Map<String, Class> idToArtifactClassMap = new HashMap<String, Class>();
+
+		// Maps to a list of types not a single type since there's no reason a single artifact couldn't be annotated
+		// with >1 batch artifact annotation type.
+		private Map<String, List<String>> idToArtifactTypeListMap = new HashMap<String, List<String>>();
+
+		/*
+		 * Init already synchronized, so no need to synch further
+		 */
+		private void addEntry(String batchTypeName, String id, String className) {
+			try {
+				if (!idToArtifactClassMap.containsKey(id)) {
+					Class<?> artifactClass = Thread.currentThread().getContextClassLoader().loadClass(className);
+
+					idToArtifactClassMap.put(id, artifactClass);
+					List<String> typeList = new ArrayList<String>();
+					typeList.add(batchTypeName);                    
+					idToArtifactTypeListMap.put(id, typeList);                    
+				} else {
+
+					Class<?> artifactClass = Thread.currentThread().getContextClassLoader().loadClass(className);
+
+					// Already contains entry for this 'id', let's make sure it's the same Class
+					// which thus must implement >1 batch artifact "type" (i.e. contains >1 batch artifact annotation).
+					if (!idToArtifactClassMap.get(id).equals(artifactClass)) {
+						if (logger.isLoggable(Level.SEVERE)) {
+							Class alreadyLoaded = idToArtifactClassMap.get(id); 
+							logger.severe("Attempted to load batch artifact with id: " + id + ", and className: " + className + 
+									".   Found: " + artifactClass + ", however the artifact id: " + id + 
+									" is already associated with: " + alreadyLoaded + ", of className: " +
+									alreadyLoaded.getCanonicalName());
+
+						}
+						throw new IllegalArgumentException("Already loaded a different class for id = " + id);
+					}
+					List<String> typeList = idToArtifactTypeListMap.get(id);
+					typeList.add(batchTypeName);
+				}
+			} catch (Exception e) {
+				throw new RuntimeException(e);
+			}
+		}
+
+		private Object getArtifactById(String id) {
+
+			Object artifactInstance = null;
+
+			try {
+				Class clazz = idToArtifactClassMap.get(id);
+				if (clazz != null) {
+					artifactInstance = (idToArtifactClassMap.get(id)).newInstance();	
+				}
+			} catch (IllegalAccessException e) {
+				throw new BatchContainerRuntimeException("Tried but failed to load artifact with id: " + id, e);
+			} catch (InstantiationException e) {
+				throw new BatchContainerRuntimeException("Tried but failed to load artifact with id: " + id, e);
+			}
+
+
+			return artifactInstance;
+		}
+
+		private List<String> getBatchTypeList(String id) {
+			return idToArtifactTypeListMap.get(id);
+		}
+
+	}
+
+	@Override
+	public void init(IBatchConfig batchConfig) throws BatchContainerServiceException {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public void shutdown() throws BatchContainerServiceException {
+		// TODO Auto-generated method stub
+
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/f7740962/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/JSEResultAdapter.java
----------------------------------------------------------------------
diff --git a/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/JSEResultAdapter.java b/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/JSEResultAdapter.java
new file mode 100755
index 0000000..6c6ab47
--- /dev/null
+++ b/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/JSEResultAdapter.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2012 International Business Machines Corp.
+ * 
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. Licensed under the Apache License, 
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+package com.ibm.jbatch.container.services.impl;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.ibm.jbatch.container.exception.BatchContainerServiceException;
+import com.ibm.jbatch.spi.services.ParallelTaskResult;
+
+/*
+ * An adapter class for a Future object so we can wait for parallel threads/steps/flows to finish before continuing 
+ */
+public class JSEResultAdapter implements ParallelTaskResult {
+
+    private final static String sourceClass = JSEResultAdapter.class.getName();
+    private final static Logger logger = Logger.getLogger(sourceClass);
+    
+    private Future result;
+    
+    public JSEResultAdapter(Future result) {
+        this.result = result;
+    }
+
+    @Override
+    public void waitForResult() {
+        try {
+            result.get();
+        } catch (InterruptedException e) {
+            throw new BatchContainerServiceException("Parallel thread was interrupted while waiting for result.", e);
+        } catch (ExecutionException e) {
+            //We will handle this case through a failed batch status. We will not propagate the exception
+            //through the entire thread.
+            if (logger.isLoggable(Level.FINE)) {
+                logger.fine(sourceClass + ": caught exception/error: " + e.getMessage() + " : Stack trace: " + e.getCause().toString());
+            }
+            
+        } catch (CancellationException e) {
+            throw new BatchContainerServiceException("Parallel thread was canceled before completion.", e);
+        }
+
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/f7740962/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/JobIdManagerImpl.java
----------------------------------------------------------------------
diff --git a/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/JobIdManagerImpl.java b/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/JobIdManagerImpl.java
new file mode 100755
index 0000000..6c59793
--- /dev/null
+++ b/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/JobIdManagerImpl.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2012 International Business Machines Corp.
+ * 
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. Licensed under the Apache License, 
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+package com.ibm.jbatch.container.services.impl;
+
+import com.ibm.jbatch.container.exception.BatchContainerServiceException;
+import com.ibm.jbatch.spi.services.IBatchConfig;
+import com.ibm.jbatch.spi.services.IJobIdManagementService;
+
+/**
+ * Used to generate job instance, job execution and step execution id
+ *
+ * @deprecated use {@link com.ibm.jbatch.container.services.impl.JDBCPersistenceManagerImpl()} instead.  
+ */
+@Deprecated
+public class JobIdManagerImpl implements IJobIdManagementService {
+//	private static final String CLASSNAME = JobIdManagerImpl.class.getName();
+//
+//	protected String rootDir;
+//	private static final String JOBID_FILE_NAME = "jobId.dat";
+//	private static Logger logger = Logger.getLogger(JobIdManagerImpl.class.getPackage().getName());
+//	
+	public void init(IBatchConfig batchConfig)
+			throws BatchContainerServiceException {
+//		rootDir = System.getProperty("user.home");
+	}
+	public void shutdown() throws BatchContainerServiceException
+	{
+	
+	}
+//	
+//    @Override
+//    public long getExecutionId() {
+//        return getId();
+//    }
+//    @Override
+//    public long getInstanceId() {
+//        return getId();
+//    }
+//    
+//    @Override
+//    public long getStepExecutionId() {
+//    	return getId();
+//    }
+//    
+//    private synchronized String getJobIdFromStorage() {
+//    	StringBuilder contents = new StringBuilder("0");
+//    	File jobIdFile = new File(rootDir + File.separator + JOBID_FILE_NAME);  
+//		if(jobIdFile.exists())
+//		{
+//				// Read the file
+//				try {
+//				  
+//				  BufferedReader input = 
+//					new BufferedReader(new FileReader(rootDir + File.separator + JOBID_FILE_NAME));
+//				  try {
+//					String line = null; 
+//					while (( line = input.readLine()) != null){
+//					  contents.append(line);
+//					  break;
+//					}
+//				  }
+//				  finally {
+//					input.close();
+//				  }
+//				}
+//				catch (IOException ex){
+//				  ex.printStackTrace();
+//				  throw new RuntimeException(ex);
+//				}
+//		}
+//		
+//		return contents.toString();
+//    }
+//    
+//    private synchronized void saveJobIdToStorage(long currentId) {
+//    	File jobIdFile = new File(rootDir + File.separator + JOBID_FILE_NAME); 
+//		try {
+//
+//			BufferedWriter output = new BufferedWriter(new FileWriter(jobIdFile));
+//			
+//			try {
+//				output.write(String.valueOf(currentId) );	
+//			} finally {
+//				output.close();
+//			}
+//
+//		} catch (IOException e) {
+//			// TODO Auto-generated catch block
+//			e.printStackTrace();
+//			throw new RuntimeException(e);
+//		}
+//    }
+//    
+//	private long getId() {
+//		
+//		String id = getJobIdFromStorage();
+//		
+//		long jobId = Long.valueOf(id);
+//	
+//		saveJobIdToStorage(++jobId);
+//	
+//		return jobId;
+//	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/f7740962/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/JobStatusManagerImpl.java
----------------------------------------------------------------------
diff --git a/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/JobStatusManagerImpl.java b/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/JobStatusManagerImpl.java
new file mode 100755
index 0000000..ad77ad9
--- /dev/null
+++ b/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/JobStatusManagerImpl.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2012 International Business Machines Corp.
+ * 
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. Licensed under the Apache License, 
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+package com.ibm.jbatch.container.services.impl;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.batch.runtime.BatchStatus;
+
+import com.ibm.jbatch.container.exception.BatchContainerServiceException;
+import com.ibm.jbatch.container.exception.PersistenceException;
+import com.ibm.jbatch.container.services.IJobStatusManagerService;
+import com.ibm.jbatch.container.services.IPersistenceManagerService;
+import com.ibm.jbatch.container.servicesmanager.ServicesManager;
+import com.ibm.jbatch.container.servicesmanager.ServicesManagerImpl;
+import com.ibm.jbatch.container.status.JobStatus;
+import com.ibm.jbatch.container.status.StepStatus;
+import com.ibm.jbatch.spi.services.IBatchConfig;
+
+public class JobStatusManagerImpl implements IJobStatusManagerService {
+
+    private static final String CLASSNAME = JobStatusManagerImpl.class.getName();
+    private static Logger logger = Logger.getLogger(JobStatusManagerImpl.class.getPackage().getName());
+    private IPersistenceManagerService _persistenceManager;    
+
+    @Override
+    public void shutdown() throws BatchContainerServiceException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public JobStatus createJobStatus(long jobInstanceId) throws BatchContainerServiceException {
+       JobStatus jobStatus = null;
+        jobStatus = _persistenceManager.createJobStatus(jobInstanceId);
+        return jobStatus;
+    }
+
+    @Override
+    public JobStatus getJobStatus(long jobInstanceId) throws BatchContainerServiceException {
+        JobStatus jobStatus = null;
+        jobStatus = _persistenceManager.getJobStatus(jobInstanceId);
+        return jobStatus;
+    }
+    
+    @Override
+    public void updateJobStatus(JobStatus jobStatus) {
+        persistJobStatus(jobStatus.getJobInstanceId(), jobStatus);
+    }
+    
+    @Override
+    public JobStatus getJobStatusFromExecutionId(long executionId) throws BatchContainerServiceException {
+    	JobStatus retVal = null;
+    	logger.fine("For executionId: " + executionId);
+    	try {
+    		retVal = _persistenceManager.getJobStatusFromExecution(executionId);
+    	} catch (PersistenceException e) {
+    		logger.warning("Did not find job instance status for executionId: " + executionId);
+    		throw e;
+    	}
+    	logger.fine("Returning : " + retVal);
+    	return retVal;
+    }
+
+    @Override
+    public void updateJobBatchStatus(long jobInstanceId, BatchStatus batchStatus) throws BatchContainerServiceException {
+        JobStatus js = getJobStatus(jobInstanceId);
+        if (js == null) {
+            throw new IllegalStateException("Couldn't find entry to update for id = " + jobInstanceId);
+        }
+        if (BatchStatus.ABANDONED.equals(js.getBatchStatus())) {
+        	logger.fine("Don't update batch status for id = " + jobInstanceId + " since it is already ABANDONED"); 
+        }
+        js.setBatchStatus(batchStatus);
+        persistJobStatus(jobInstanceId, js);
+    }
+
+    @Override
+    public void updateJobExecutionStatus(long jobInstanceId, BatchStatus batchStatus, String exitStatus) throws BatchContainerServiceException {
+        JobStatus js = getJobStatus(jobInstanceId);
+        if (js == null) {
+            throw new IllegalStateException("Couldn't find entry to update for id = " + jobInstanceId);
+        }
+        js.setBatchStatus(batchStatus);
+        js.setExitStatus(exitStatus);
+        persistJobStatus(jobInstanceId, js);
+    }
+
+    @Override
+    public void updateJobCurrentStep(long jobInstanceId, String currentStepName) throws BatchContainerServiceException {
+        JobStatus js = getJobStatus(jobInstanceId);
+        if (js == null) {
+            throw new IllegalStateException("Couldn't find entry to update for id = " + jobInstanceId);
+        }
+        js.setCurrentStepId(currentStepName);
+        persistJobStatus(jobInstanceId, js);        
+    }
+
+
+    @Override
+    public void updateJobStatusWithNewExecution(long jobInstanceId, long newExecutionId) throws BatchContainerServiceException {
+        JobStatus js = getJobStatus(jobInstanceId);
+        if (js == null) {
+            throw new IllegalStateException("Couldn't find entry to update for id = " + jobInstanceId);
+        }
+        js.setRestartOn(null);
+        js.setLatestExecutionId(newExecutionId);
+        js.setBatchStatus(BatchStatus.STARTING);
+        persistJobStatus(jobInstanceId, js);                
+    }
+
+    private void persistJobStatus(long jobInstanceId, JobStatus newJobStatus) throws BatchContainerServiceException {       
+        _persistenceManager.updateJobStatus(jobInstanceId, newJobStatus);
+    }
+
+    @Override
+    public StepStatus createStepStatus(long stepExecutionId) throws BatchContainerServiceException {        
+        return _persistenceManager.createStepStatus(stepExecutionId);
+    }
+
+    @Override
+    /*
+     * @return - StepStatus or null if one is unknown
+     */
+    public StepStatus getStepStatus(long jobInstanceId, String stepId) throws BatchContainerServiceException {
+        String method = "getStepStatus";
+        logger.entering(CLASSNAME, method, new Object[] {jobInstanceId, stepId});
+
+        StepStatus stepStatus = _persistenceManager.getStepStatus(jobInstanceId, stepId);
+
+        logger.exiting(CLASSNAME, method, stepStatus==null ? "<null>" : stepStatus);
+        return stepStatus;
+    }
+
+    @Override 
+    public void updateStepStatus(long stepExecutionId, StepStatus newStepStatus) {
+        String method = "updateStepStatus";
+        logger.entering(CLASSNAME, method, new Object[] {stepExecutionId, newStepStatus});
+        _persistenceManager.updateStepStatus(stepExecutionId, newStepStatus);
+        logger.exiting(CLASSNAME, method);
+    }
+
+    @Override
+    public void init(IBatchConfig batchConfig)
+    throws BatchContainerServiceException {
+        String method = "init";
+        if(logger.isLoggable(Level.FINER)) { logger.entering(CLASSNAME, method);}
+
+        ServicesManager sm = ServicesManagerImpl.getInstance();
+
+        _persistenceManager = sm.getPersistenceManagerService();
+
+        if(logger.isLoggable(Level.FINER)) { logger.exiting(CLASSNAME, method);}
+    }
+
+    @Override
+    /*
+     * Inefficient, since we've already updated the status to stopped.. would be better to have a single update.
+     */
+    public void updateJobStatusFromJSLStop(long jobInstanceId, String restartOn) throws BatchContainerServiceException {       
+        JobStatus js = getJobStatus(jobInstanceId);        
+        if (js == null) {
+            throw new IllegalStateException("Couldn't find entry to update for id = " + jobInstanceId);
+        }
+        js.setRestartOn(restartOn);
+        persistJobStatus(jobInstanceId, js);   
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/f7740962/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/NoOpBatchSecurityHelper.java
----------------------------------------------------------------------
diff --git a/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/NoOpBatchSecurityHelper.java b/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/NoOpBatchSecurityHelper.java
new file mode 100755
index 0000000..00d6e1a
--- /dev/null
+++ b/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/NoOpBatchSecurityHelper.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2013 International Business Machines Corp.
+ * 
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. Licensed under the Apache License, 
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ibm.jbatch.container.services.impl;
+
+import com.ibm.jbatch.spi.BatchSecurityHelper;
+
+public class NoOpBatchSecurityHelper implements BatchSecurityHelper {
+
+	private static final String APPTAG = "NOTSET";
+	
+	public NoOpBatchSecurityHelper() {}
+	
+	@Override
+	public String getCurrentTag() {
+		return APPTAG;
+	}
+
+	@Override
+	public boolean isAdmin(String tag) {
+		return tag.equals(APPTAG);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/f7740962/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/RuntimeBatchJobUtil.java
----------------------------------------------------------------------
diff --git a/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/RuntimeBatchJobUtil.java b/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/RuntimeBatchJobUtil.java
new file mode 100755
index 0000000..25e9708
--- /dev/null
+++ b/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/RuntimeBatchJobUtil.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2013 International Business Machines Corp.
+ * 
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. Licensed under the Apache License, 
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ibm.jbatch.container.services.impl;
+
+import javax.batch.runtime.BatchRuntime;
+
+import com.ibm.jbatch.container.api.impl.JobOperatorImpl;
+import com.ibm.jbatch.spi.BatchJobUtil;
+
+public class RuntimeBatchJobUtil implements BatchJobUtil {
+
+	@Override
+	public void purgeOwnedRepositoryData(String tag) {
+		
+		JobOperatorImpl jobOperator = (JobOperatorImpl) BatchRuntime.getJobOperator();
+		jobOperator.purge(tag);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/f7740962/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/SPIDelegatingThreadPoolServiceImpl.java
----------------------------------------------------------------------
diff --git a/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/SPIDelegatingThreadPoolServiceImpl.java b/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/SPIDelegatingThreadPoolServiceImpl.java
new file mode 100755
index 0000000..383a1ec
--- /dev/null
+++ b/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/SPIDelegatingThreadPoolServiceImpl.java
@@ -0,0 +1,79 @@
+/**
+ * Copyright 2013 International Business Machines Corp.
+ *
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. Licensed under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ibm.jbatch.container.services.impl;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.ibm.jbatch.container.exception.BatchContainerServiceException;
+import com.ibm.jbatch.spi.BatchSPIManager;
+import com.ibm.jbatch.spi.services.IBatchConfig;
+import com.ibm.jbatch.spi.services.IBatchThreadPoolService;
+import com.ibm.jbatch.spi.services.ParallelTaskResult;
+
+public class SPIDelegatingThreadPoolServiceImpl implements IBatchThreadPoolService {
+	
+	private final static String sourceClass = SPIDelegatingThreadPoolServiceImpl.class.getName();
+	private final static Logger logger = Logger.getLogger(sourceClass);
+
+	public SPIDelegatingThreadPoolServiceImpl() {
+		// TODO Auto-generated constructor stub
+	}
+
+	@Override
+	public void init(IBatchConfig batchConfig) {
+		// Don't want to get/cache anything here since we want to delegate each time.
+	}
+
+	
+	public void shutdown() throws BatchContainerServiceException {
+		String method = "shutdown";
+		if(logger.isLoggable(Level.FINER)) { logger.entering(sourceClass, method);	}
+		
+		ExecutorService delegateService = BatchSPIManager.getInstance().getExecutorServiceProvider().getExecutorService();
+		delegateService.shutdownNow();
+		
+		if(logger.isLoggable(Level.FINER)) { logger.exiting(sourceClass, method);	}
+	}
+
+	public void executeTask(Runnable work, Object config) {
+		String method = "executeTask";
+		if(logger.isLoggable(Level.FINER)) { logger.entering(sourceClass, method);	}
+		
+		ExecutorService delegateService = BatchSPIManager.getInstance().getExecutorServiceProvider().getExecutorService();
+		delegateService.execute(work);
+		
+		if(logger.isLoggable(Level.FINER)) { logger.exiting(sourceClass, method);	}
+	}
+
+    public ParallelTaskResult executeParallelTask(Runnable work, Object config) {
+        String method = "executeParallelTask";
+        if(logger.isLoggable(Level.FINER)) { logger.entering(sourceClass, method);  }
+        
+		ExecutorService delegateService = BatchSPIManager.getInstance().getExecutorServiceProvider().getExecutorService();
+        Future result = delegateService.submit(work);
+        ParallelTaskResult taskResult = new JSEResultAdapter(result);
+        
+        if(logger.isLoggable(Level.FINER)) { logger.exiting(sourceClass, method);   }
+        
+        return taskResult;
+    }
+	
+	
+}

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/f7740962/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/WeldSEBatchArtifactFactoryImpl.java
----------------------------------------------------------------------
diff --git a/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/WeldSEBatchArtifactFactoryImpl.java b/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/WeldSEBatchArtifactFactoryImpl.java
new file mode 100755
index 0000000..21dbd5c
--- /dev/null
+++ b/JSR352.Runtime/src/com/ibm/jbatch/container/services/impl/WeldSEBatchArtifactFactoryImpl.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2012 International Business Machines Corp.
+ * 
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. Licensed under the Apache License, 
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ibm.jbatch.container.services.impl;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.inject.Named;
+
+import org.jboss.weld.environment.se.Weld;
+import org.jboss.weld.environment.se.WeldContainer;
+
+import com.ibm.jbatch.container.exception.BatchContainerServiceException;
+import com.ibm.jbatch.spi.services.IBatchArtifactFactory;
+import com.ibm.jbatch.spi.services.IBatchConfig;
+
+@Named("MyWeldBean")
+public class WeldSEBatchArtifactFactoryImpl implements IBatchArtifactFactory {
+
+    private final static Logger logger = Logger.getLogger(WeldSEBatchArtifactFactoryImpl.class.getName());
+    private final static String CLASSNAME = WeldSEBatchArtifactFactoryImpl.class.getName();
+
+    // TODO - synchronize appropriately once we learn more about usage
+    private boolean loaded = false;
+
+    // Uses TCCL
+    @Override
+    public Object load(String batchId) {
+        String methodName = "load";
+
+        if (logger.isLoggable(Level.FINER)) {
+            logger.entering(CLASSNAME, methodName, "Loading batch artifact id = " + batchId);
+        }
+
+        Object loadedArtifact = getArtifactById(batchId);
+
+        if (loadedArtifact == null) {
+            
+            logger.exiting(CLASSNAME, methodName, "Returning null artifact for id: " + batchId);
+            
+            return loadedArtifact;
+
+        }
+
+        if (logger.isLoggable(Level.FINER)) {
+            logger.exiting(CLASSNAME, methodName, "For batch artifact id = " + batchId + ", loaded artifact instance: " + loadedArtifact
+                    + " of type: " + loadedArtifact.getClass().getCanonicalName());
+        }
+        return loadedArtifact;
+    }
+
+    private Object getArtifactById(String id) {
+
+
+        
+        Object artifactInstance = null;
+
+        try {
+        WeldContainer weld = new Weld().initialize();
+        BeanManager bm = weld.getBeanManager();
+
+        Bean bean = bm.getBeans(id).iterator().next();
+
+        Class clazz = bean.getBeanClass();
+        
+        artifactInstance = bm.getReference(bean, clazz, bm.createCreationalContext(bean));
+        } catch (Exception e) {
+            // Don't throw an exception but simply return null;
+            logger.fine("Tried but failed to load artifact with id: " + id + ", Exception = " + e);
+        }
+        return artifactInstance;
+        
+    }
+
+    @Override
+    public void init(IBatchConfig batchConfig) throws BatchContainerServiceException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void shutdown() throws BatchContainerServiceException {
+        // TODO Auto-generated method stub
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/f7740962/JSR352.Runtime/src/com/ibm/jbatch/container/services/package-info.java
----------------------------------------------------------------------
diff --git a/JSR352.Runtime/src/com/ibm/jbatch/container/services/package-info.java b/JSR352.Runtime/src/com/ibm/jbatch/container/services/package-info.java
new file mode 100755
index 0000000..384fbce
--- /dev/null
+++ b/JSR352.Runtime/src/com/ibm/jbatch/container/services/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2013 International Business Machines Corp.
+ * 
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. Licensed under the Apache License, 
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+/**
+ * This interfaces are tightly coupled to the existing
+ * batch implementation.
+ */
+package com.ibm.jbatch.container.services;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/f7740962/JSR352.Runtime/src/com/ibm/jbatch/container/servicesmanager/ServiceTypes.java
----------------------------------------------------------------------
diff --git a/JSR352.Runtime/src/com/ibm/jbatch/container/servicesmanager/ServiceTypes.java b/JSR352.Runtime/src/com/ibm/jbatch/container/servicesmanager/ServiceTypes.java
new file mode 100755
index 0000000..d98d2f3
--- /dev/null
+++ b/JSR352.Runtime/src/com/ibm/jbatch/container/servicesmanager/ServiceTypes.java
@@ -0,0 +1,111 @@
+/**
+ * Copyright 2013 International Business Machines Corp.
+ *
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. Licensed under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ibm.jbatch.container.servicesmanager;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class ServiceTypes {
+	
+	public enum Name {
+		JAVA_EDITION_IS_SE_DUMMY_SERVICE, 
+		TRANSACTION_SERVICE, 
+		PERSISTENCE_MANAGEMENT_SERVICE, 
+		JOB_STATUS_MANAGEMENT_SERVICE, 
+		BATCH_THREADPOOL_SERVICE, 
+		BATCH_KERNEL_SERVICE, 
+		JOB_ID_MANAGEMENT_SERVICE, 
+		CALLBACK_SERVICE, 
+		JOBXML_LOADER_SERVICE,                // Preferred
+		DELEGATING_JOBXML_LOADER_SERVICE,      // Delegating wrapper
+		CONTAINER_ARTIFACT_FACTORY_SERVICE,   // Preferred
+		DELEGATING_ARTIFACT_FACTORY_SERVICE  // Delegating wrapper
+	}
+	
+	public static final String J2SE_MODE = "J2SE_MODE"; // Trying to preserve  this value since we already shared it.
+	public static final String TRANSACTION_SERVICE = "TRANSACTION_SERVICE";
+	public static final String PERSISTENCE_MANAGEMENT_SERVICE = "PERSISTENCE_MANAGEMENT_SERVICE";
+	public static final String JOB_STATUS_MANAGEMENT_SERVICE = "JOB_STATUS_MANAGEMENT_SERVICE";
+	public static final String BATCH_THREADPOOL_SERVICE = "BATCH_THREADPOOL_SERVICE";
+	public static final String BATCH_KERNEL_SERVICE = "BATCH_KERNEL_SERVICE";
+	public static final String JOB_ID_MANAGEMENT_SERVICE = "JOB_ID_MANAGEMENT_SERVICE";
+	public static final String CALLBACK_SERVICE = "CALLBACK_SERVICE";
+	public static final String JOBXML_LOADER_SERVICE = "JOBXML_LOADER_SERVICE";
+	public static final String DELEGATING_JOBXML_LOADER_SERVICE = "DELEGATING_JOBXML_LOADER_SERVICE";
+	public static final String CONTAINER_ARTIFACT_FACTORY_SERVICE = "CONTAINER_ARTIFACT_FACTORY_SERVICE";
+	public static final String DELEGATING_ARTIFACT_FACTORY_SERVICE = "DELEGATING_ARTIFACT_FACTORY_SERVICE";
+
+	// The purpose of the awkwardness of complexity of treating SE vs EE as a
+	// "service" is to emphasize the fact that it's something an
+	// integrator of the RI into a new environment would configure, rather than
+	// a "batch admin".
+	private static final String DEFAULT_JAVA_EDITION_IS_SE_DUMMY_SERVICE = "false";
+	private static final String DEFAULT_TRANSACTION_SERVICE = "com.ibm.jbatch.container.services.impl.BatchTransactionServiceImpl";
+	private static final String DEFAULT_PERSISTENCE_MGR_CLASS = "com.ibm.jbatch.container.services.impl.JDBCPersistenceManagerImpl";
+	private static final String DEFAULT_JOBSTATUS_MGR_SERVICE = "com.ibm.jbatch.container.services.impl.JobStatusManagerImpl";
+	private static final String DEFAULT_BATCH_THREADPOOL_SERVICE = "com.ibm.jbatch.container.services.impl.GrowableThreadPoolServiceImpl";
+	private static final String DEFAULT_BATCH_KERNEL_SERVICE = "com.ibm.jbatch.container.impl.BatchKernelImpl";
+	private static final String DEFAULT_JOBID_MGR_SERVICE = "com.ibm.jbatch.container.services.impl.JobIdManagerImpl";
+	private static final String DEFAULT_CALLBACK_SERVICE = "com.ibm.jbatch.container.callback.JobEndCallbackManagerImpl";
+	private static final String DEFAULT_JOBXML_LOADER_SERVICE = "com.ibm.jbatch.container.services.impl.DelegatingJobXMLLoaderServiceImpl";
+	private static final String DEFAULT_DELEGATING_JOBXML_LOADER_SERVICE = "com.ibm.jbatch.container.services.impl.DelegatingJobXMLLoaderServiceImpl";
+	private static final String DEFAULT_CONTAINER_ARTIFACT_FACTORY_SERVICE = "com.ibm.jbatch.container.services.impl.DelegatingBatchArtifactFactoryImpl";
+	private static final String DEFAULT_DELEGATING_ARTIFACT_FACTORY_SERVICE = "com.ibm.jbatch.container.services.impl.DelegatingBatchArtifactFactoryImpl";
+
+	private static Map<String, Name> servicePropertyNames;
+	static { 
+		servicePropertyNames = new ConcurrentHashMap<String, Name>();
+		servicePropertyNames.put(J2SE_MODE, Name.JAVA_EDITION_IS_SE_DUMMY_SERVICE);
+		servicePropertyNames.put(TRANSACTION_SERVICE, Name.TRANSACTION_SERVICE);
+		servicePropertyNames.put(PERSISTENCE_MANAGEMENT_SERVICE, Name.PERSISTENCE_MANAGEMENT_SERVICE);
+		servicePropertyNames.put(JOB_STATUS_MANAGEMENT_SERVICE, Name.JOB_STATUS_MANAGEMENT_SERVICE);
+		servicePropertyNames.put(BATCH_THREADPOOL_SERVICE, Name.BATCH_THREADPOOL_SERVICE);
+		servicePropertyNames.put(BATCH_KERNEL_SERVICE, Name.BATCH_KERNEL_SERVICE);
+		servicePropertyNames.put(JOB_ID_MANAGEMENT_SERVICE, Name.JOB_ID_MANAGEMENT_SERVICE);
+		servicePropertyNames.put(CALLBACK_SERVICE, Name.CALLBACK_SERVICE);
+		servicePropertyNames.put(JOBXML_LOADER_SERVICE, Name.JOBXML_LOADER_SERVICE);
+		servicePropertyNames.put(DELEGATING_JOBXML_LOADER_SERVICE, Name.DELEGATING_JOBXML_LOADER_SERVICE);
+		servicePropertyNames.put(CONTAINER_ARTIFACT_FACTORY_SERVICE, Name.CONTAINER_ARTIFACT_FACTORY_SERVICE);
+		servicePropertyNames.put(DELEGATING_ARTIFACT_FACTORY_SERVICE, Name.DELEGATING_ARTIFACT_FACTORY_SERVICE);
+	}
+	
+	public static Map<String, Name> getServicePropertyNames() {
+		return servicePropertyNames;
+	}
+	
+	// Use class names instead of Class objects to not drag in any dependencies);
+	private static Map<Name, String> serviceImplClassNames;
+	static { 
+		serviceImplClassNames = new ConcurrentHashMap<Name, String>();
+		serviceImplClassNames.put(Name.JAVA_EDITION_IS_SE_DUMMY_SERVICE, DEFAULT_JAVA_EDITION_IS_SE_DUMMY_SERVICE);
+		serviceImplClassNames.put(Name.TRANSACTION_SERVICE, DEFAULT_TRANSACTION_SERVICE);
+		serviceImplClassNames.put(Name.PERSISTENCE_MANAGEMENT_SERVICE, DEFAULT_PERSISTENCE_MGR_CLASS);
+		serviceImplClassNames.put(Name.JOB_STATUS_MANAGEMENT_SERVICE, DEFAULT_JOBSTATUS_MGR_SERVICE);
+		serviceImplClassNames.put(Name.BATCH_THREADPOOL_SERVICE, DEFAULT_BATCH_THREADPOOL_SERVICE);
+		serviceImplClassNames.put(Name.BATCH_KERNEL_SERVICE, DEFAULT_BATCH_KERNEL_SERVICE);
+		serviceImplClassNames.put(Name.JOB_ID_MANAGEMENT_SERVICE, DEFAULT_JOBID_MGR_SERVICE);
+		serviceImplClassNames.put(Name.CALLBACK_SERVICE, DEFAULT_CALLBACK_SERVICE);
+		serviceImplClassNames.put(Name.JOBXML_LOADER_SERVICE, DEFAULT_JOBXML_LOADER_SERVICE);
+		serviceImplClassNames.put(Name.DELEGATING_JOBXML_LOADER_SERVICE, DEFAULT_DELEGATING_JOBXML_LOADER_SERVICE);
+		serviceImplClassNames.put(Name.CONTAINER_ARTIFACT_FACTORY_SERVICE, DEFAULT_CONTAINER_ARTIFACT_FACTORY_SERVICE); 
+		serviceImplClassNames.put(Name.DELEGATING_ARTIFACT_FACTORY_SERVICE, DEFAULT_DELEGATING_ARTIFACT_FACTORY_SERVICE);
+	}
+	
+	public static Map<Name, String> getServiceImplClassNames() {
+		return serviceImplClassNames;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/f7740962/JSR352.Runtime/src/com/ibm/jbatch/container/servicesmanager/ServicesManager.java
----------------------------------------------------------------------
diff --git a/JSR352.Runtime/src/com/ibm/jbatch/container/servicesmanager/ServicesManager.java b/JSR352.Runtime/src/com/ibm/jbatch/container/servicesmanager/ServicesManager.java
new file mode 100755
index 0000000..8a27b1c
--- /dev/null
+++ b/JSR352.Runtime/src/com/ibm/jbatch/container/servicesmanager/ServicesManager.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright 2013 International Business Machines Corp.
+ *
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. Licensed under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ibm.jbatch.container.servicesmanager;
+
+import com.ibm.jbatch.container.callback.IJobEndCallbackService;
+import com.ibm.jbatch.container.services.IBatchKernelService;
+import com.ibm.jbatch.container.services.IJobStatusManagerService;
+import com.ibm.jbatch.container.services.IPersistenceManagerService;
+import com.ibm.jbatch.spi.services.IBatchArtifactFactory;
+import com.ibm.jbatch.spi.services.IBatchThreadPoolService;
+import com.ibm.jbatch.spi.services.IJobIdManagementService;
+import com.ibm.jbatch.spi.services.IJobXMLLoaderService;
+import com.ibm.jbatch.spi.services.ITransactionManagementService;
+
+public interface ServicesManager {
+	public IPersistenceManagerService getPersistenceManagerService();
+	public IJobStatusManagerService getJobStatusManagerService();
+	public IJobIdManagementService getJobIdManagementService();
+	public ITransactionManagementService getTransactionManagementService();
+	public IJobEndCallbackService getJobCallbackService();
+	public IBatchKernelService getBatchKernelService();
+	public IJobXMLLoaderService getDelegatingJobXMLLoaderService();
+	public IJobXMLLoaderService getPreferredJobXMLLoaderService();
+	public IBatchThreadPoolService getThreadPoolService();
+	public IBatchArtifactFactory getDelegatingArtifactFactory();
+	public IBatchArtifactFactory getPreferredArtifactFactory();
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/f7740962/JSR352.Runtime/src/com/ibm/jbatch/container/servicesmanager/ServicesManagerImpl.java
----------------------------------------------------------------------
diff --git a/JSR352.Runtime/src/com/ibm/jbatch/container/servicesmanager/ServicesManagerImpl.java b/JSR352.Runtime/src/com/ibm/jbatch/container/servicesmanager/ServicesManagerImpl.java
new file mode 100755
index 0000000..77fb7dc
--- /dev/null
+++ b/JSR352.Runtime/src/com/ibm/jbatch/container/servicesmanager/ServicesManagerImpl.java
@@ -0,0 +1,416 @@
+/*
+ * 
+ * Copyright 2012,2013 International Business Machines Corp.
+ * 
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. Licensed under the Apache License, 
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ibm.jbatch.container.servicesmanager;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.ibm.jbatch.container.callback.IJobEndCallbackService;
+import com.ibm.jbatch.container.exception.BatchContainerServiceException;
+import com.ibm.jbatch.container.exception.PersistenceException;
+import com.ibm.jbatch.container.impl.BatchConfigImpl;
+import com.ibm.jbatch.container.services.IBatchKernelService;
+import com.ibm.jbatch.container.services.IJobStatusManagerService;
+import com.ibm.jbatch.container.services.IPersistenceManagerService;
+import com.ibm.jbatch.container.servicesmanager.ServiceTypes.Name;
+import com.ibm.jbatch.container.util.BatchContainerConstants;
+import com.ibm.jbatch.spi.BatchSPIManager;
+import com.ibm.jbatch.spi.DatabaseConfigurationBean;
+import com.ibm.jbatch.spi.services.IBatchArtifactFactory;
+import com.ibm.jbatch.spi.services.IBatchServiceBase;
+import com.ibm.jbatch.spi.services.IBatchThreadPoolService;
+import com.ibm.jbatch.spi.services.IJobIdManagementService;
+import com.ibm.jbatch.spi.services.IJobXMLLoaderService;
+import com.ibm.jbatch.spi.services.ITransactionManagementService;
+
+public class ServicesManagerImpl implements BatchContainerConstants, ServicesManager {
+
+	private final static String sourceClass = ServicesManagerImpl.class.getName();
+	private final static Logger logger = Logger.getLogger(sourceClass);
+	
+	private ServicesManagerImpl() { } 
+	
+	// Lazily-loaded singleton.
+	private static class ServicesManagerImplHolder {
+		private static final ServicesManagerImpl INSTANCE = new ServicesManagerImpl();
+	}
+
+	public static ServicesManager getInstance() {
+		return ServicesManagerImplHolder.INSTANCE;
+	}
+	
+	// Declared 'volatile' to allow use in double-checked locking.  This 'isInited'
+	// refers to whether the configuration has been hardened and possibly the
+	// first service impl loaded, not whether the instance has merely been instantiated.
+	private final byte[] isInitedLock = new byte[0];
+	private volatile Boolean isInited = Boolean.FALSE;
+
+	private DatabaseConfigurationBean databaseConfigBean = null;
+	private BatchConfigImpl batchRuntimeConfig;
+	private Properties batchContainerProps = null;
+
+	
+	private	Map<Name, String> serviceImplClassNames = ServiceTypes.getServiceImplClassNames();
+	private Map<String, Name> propertyNameTable = ServiceTypes.getServicePropertyNames();
+
+	// Registry of all current services
+	private final ConcurrentHashMap<Name, IBatchServiceBase> serviceRegistry = new ConcurrentHashMap<Name, IBatchServiceBase>();
+	
+	/**
+	 * Init doesn't actually load the service impls, which are still loaded lazily.   What it does is it
+	 * hardens the config.  This is necessary since the batch runtime by and large is not dynamically
+	 * configurable, (e.g. via MBeans).  Things like the database config used by the batch runtime's
+	 * persistent store are hardened then, as are the names of the service impls to use.
+	 */
+	private void initIfNecessary() {
+		if (logger.isLoggable(Level.FINER)) {
+			logger.config("In initIfNecessary().");
+		}
+		// Use double-checked locking with volatile.
+		if (!isInited) {
+			synchronized (isInitedLock) {
+				if (!isInited) {
+					logger.config("--- Initializing ServicesManagerImpl ---");
+					batchRuntimeConfig = new BatchConfigImpl();
+
+					initFromPropertiesFiles();
+					initServiceImplOverrides();
+					initDatabaseConfig();
+					initOtherConfig();
+					isInited = Boolean.TRUE;
+					
+					logger.config("--- Completed initialization of ServicesManagerImpl ---");
+				}
+			}
+		}
+
+		logger.config("Exiting initIfNecessary()");
+	}
+
+	private void initFromPropertiesFiles() {
+
+		Properties serviceIntegratorProps = new Properties();
+		InputStream batchServicesListInputStream = this.getClass()
+				.getResourceAsStream("/META-INF/services/" + BATCH_INTEGRATOR_CONFIG_FILE);
+
+		if (batchServicesListInputStream != null) {
+			try {
+				logger.config("Batch Integrator Config File exists! loading it..");
+				serviceIntegratorProps.load(batchServicesListInputStream);
+				batchServicesListInputStream.close();
+			} catch (IOException e) {
+				logger.config("Error loading " + "/META-INF/services/" + BATCH_INTEGRATOR_CONFIG_FILE + " IOException=" + e.toString());
+			} catch (Exception e) {
+				logger.config("Error loading " + "/META-INF/services/" + BATCH_INTEGRATOR_CONFIG_FILE + " Exception=" + e.toString());
+			}
+		} else {
+			logger.config("Could not find batch integrator config file: " + "/META-INF/services/" + BATCH_INTEGRATOR_CONFIG_FILE);
+		}
+
+		// See if any do not map to service impls.
+
+		Set<String> removeThese = new HashSet<String>();
+		for (Object key : serviceIntegratorProps.keySet()) {
+			String keyStr = (String) key;
+			if (!propertyNameTable.containsKey(keyStr)) {
+				logger.warning("Found property named: " + keyStr
+						+ " with value: " + serviceIntegratorProps.get(keyStr)
+						+ " in " + BATCH_INTEGRATOR_CONFIG_FILE + " , but did not find a corresponding service type "
+						+ "in the internal table of service types.\n Ignoring this property then.   Maybe this should have been set in batch-config.properties instead.");
+				removeThese.add(keyStr);
+			}
+		}
+		for (String s : removeThese) {
+			serviceIntegratorProps.remove(s);
+		}
+
+		Properties adminProps = new Properties();
+		InputStream batchAdminConfigListInputStream = this.getClass().getResourceAsStream("/META-INF/services/" + BATCH_ADMIN_CONFIG_FILE);
+
+		if (batchServicesListInputStream != null) {
+			try {
+				logger.config("Batch Admin Config File exists! loading it..");
+				adminProps.load(batchAdminConfigListInputStream);
+				batchAdminConfigListInputStream.close();
+			} catch (IOException e) {
+				logger.config("Error loading " + "/META-INF/services/" + BATCH_ADMIN_CONFIG_FILE + " IOException=" + e.toString());
+			} catch (Exception e) {
+				logger.config("Error loading " + "/META-INF/services/" + BATCH_ADMIN_CONFIG_FILE + " Exception=" + e.toString());
+			}
+		} else {
+			logger.config("Could not find batch admin config file: " + "/META-INF/services/" + BATCH_ADMIN_CONFIG_FILE);
+		}
+
+		// See if any DO map to service impls, which would be a mistake
+		Set<String> removeTheseToo = new HashSet<String>();
+		for (Object key : adminProps.keySet()) {
+			String keyStr = (String) key;
+			if (propertyNameTable.containsKey(keyStr)) {
+				logger.warning("Found property named: " + keyStr + " with value: " + adminProps.get(keyStr) + " in "
+						+ BATCH_ADMIN_CONFIG_FILE + " , but this is a batch runtime service configuration.\n"
+						+ "Ignoring this property then, since this should have been set in batch-services.properties instead.");
+				removeThese.add(keyStr);
+			}
+		}
+		for (String s : removeTheseToo) {
+			adminProps.remove(s);
+		}
+
+		// Merge the two into 'batchContainerProps'
+		batchContainerProps = new Properties();
+		batchContainerProps.putAll(adminProps);
+		batchContainerProps.putAll(serviceIntegratorProps);
+
+		logger.fine("Dumping contents of batchContainerProps after reading properties files.");
+		for (Object key : batchContainerProps.keySet()) {
+			logger.config("key = " + key);
+			logger.config("value = " + batchContainerProps.get(key));
+		}
+		
+		// Set this on the config. 
+		// 
+		// WARNING:  This sets us up for collisions since this is just a single holder of properties
+		// potentially used by any service impl.
+		batchRuntimeConfig.setConfigProperties(batchContainerProps);
+	}
+
+	private void initServiceImplOverrides() {
+		
+		// For each property we care about (i.e that defines one of our service impls)
+		for (String propKey : propertyNameTable.keySet()) {
+			// If the property is defined
+			String value = batchContainerProps.getProperty(propKey);
+			if (value != null) {
+				// Get the corresponding serviceType enum and store the value of
+				// the key/value property pair in the table where we store the service impl classnames.
+				Name serviceType = propertyNameTable.get(propKey);
+				String defaultServiceImplClassName = serviceImplClassNames.get(serviceType); // For logging.
+				serviceImplClassNames.put(serviceType, value.trim());
+				logger.config("Overriding serviceType: " + serviceType + ", replacing default impl classname: " + 
+							defaultServiceImplClassName + " with override impl class name: " + value.trim());
+			}
+		}
+	}
+
+	private void initDatabaseConfig() {
+		if (databaseConfigBean == null) { 
+			logger.config("First try to load 'suggested config' from BatchSPIManager");
+			databaseConfigBean = BatchSPIManager.getInstance().getFinalDatabaseConfiguration();
+			if (databaseConfigBean == null) { 
+				logger.fine("Loading database config from configuration properties file.");
+				// Initialize database-related properties
+				databaseConfigBean = new DatabaseConfigurationBean();
+				databaseConfigBean.setJndiName(batchContainerProps.getProperty(JNDI_NAME, DEFAULT_JDBC_JNDI_NAME));
+				databaseConfigBean.setJdbcDriver(batchContainerProps.getProperty(JDBC_DRIVER, DEFAULT_JDBC_DRIVER));
+				databaseConfigBean.setJdbcUrl(batchContainerProps.getProperty(JDBC_URL, DEFAULT_JDBC_URL));
+				databaseConfigBean.setDbUser(batchContainerProps.getProperty(DB_USER));
+				databaseConfigBean.setDbPassword(batchContainerProps.getProperty(DB_PASSWORD));
+				databaseConfigBean.setSchema(batchContainerProps.getProperty(DB_SCHEMA, DEFAULT_DB_SCHEMA));
+			}
+		}  else {
+			// Currently we do not expected this path to be used by Glassfish
+			logger.config("Database config has been set directly from SPI, do NOT load from properties file.");
+		}
+		// In either case, set this bean on the main config bean
+		batchRuntimeConfig.setDatabaseConfigurationBean(databaseConfigBean);
+	}
+
+
+	private void initOtherConfig() {
+		String seMode = serviceImplClassNames.get(Name.JAVA_EDITION_IS_SE_DUMMY_SERVICE);
+		if (seMode.equalsIgnoreCase("true")) {
+			batchRuntimeConfig.setJ2seMode(true);
+		}
+	}
+
+	// Look up registry and return requested service if exist
+	// If not exist, create a new one, add to registry and return that one
+	/* (non-Javadoc)
+	 * @see com.ibm.jbatch.container.config.ServicesManager#getService(com.ibm.jbatch.container.config.ServicesManagerImpl.ServiceType)
+	 */
+	private IBatchServiceBase getService(Name serviceType) throws BatchContainerServiceException {
+		String sourceMethod = "getService";
+		if (logger.isLoggable(Level.FINE))
+			logger.entering(sourceClass, sourceMethod + ", serviceType=" + serviceType);
+
+		initIfNecessary();
+
+		IBatchServiceBase service = new ServiceLoader(serviceType).getService();
+
+		if (logger.isLoggable(Level.FINE))
+			logger.exiting(sourceClass, sourceMethod);
+
+		return service;
+	}
+
+	/*
+	 * 	public enum Name {
+		JAVA_EDITION_IS_SE_DUMMY_SERVICE, 
+		TRANSACTION_SERVICE, 
+		PERSISTENCE_MANAGEMENT_SERVICE, 
+		JOB_STATUS_MANAGEMENT_SERVICE, 
+		BATCH_THREADPOOL_SERVICE, 
+		BATCH_KERNEL_SERVICE, 
+		JOB_ID_MANAGEMENT_SERVICE, 
+		CALLBACK_SERVICE, 
+		JOBXML_LOADER_SERVICE,                // Preferred
+		DELEGATING_JOBXML_LOADER_SERVICE,      // Delegating wrapper
+		CONTAINER_ARTIFACT_FACTORY_SERVICE,   // Preferred
+		DELEGATING_ARTIFACT_FACTORY_SERVICE  // Delegating wrapper
+	 */
+	
+	@Override
+	public ITransactionManagementService getTransactionManagementService() {
+		return (ITransactionManagementService)getService(Name.TRANSACTION_SERVICE);
+	}
+
+	@Override
+	public IPersistenceManagerService getPersistenceManagerService() {
+		return (IPersistenceManagerService)getService(Name.PERSISTENCE_MANAGEMENT_SERVICE);
+	}
+
+	@Override
+	public IJobStatusManagerService getJobStatusManagerService() {
+		return (IJobStatusManagerService)getService(Name.JOB_STATUS_MANAGEMENT_SERVICE);
+	}
+
+	@Override
+	public IBatchThreadPoolService getThreadPoolService() {
+		return (IBatchThreadPoolService)getService(Name.BATCH_THREADPOOL_SERVICE);
+	}
+
+	@Override
+	public IBatchKernelService getBatchKernelService() {
+		return (IBatchKernelService)getService(Name.BATCH_KERNEL_SERVICE);
+	}
+
+	@Override
+	public IJobIdManagementService getJobIdManagementService() {
+		return (IJobIdManagementService)getService(Name.JOB_ID_MANAGEMENT_SERVICE);
+	}
+
+	@Override
+	public IJobEndCallbackService getJobCallbackService() {
+		return (IJobEndCallbackService)getService(Name.CALLBACK_SERVICE);
+	}
+
+	@Override
+	public IJobXMLLoaderService getPreferredJobXMLLoaderService() {
+		return (IJobXMLLoaderService)getService(Name.JOBXML_LOADER_SERVICE);
+	}
+
+	@Override
+	public IJobXMLLoaderService getDelegatingJobXMLLoaderService() {
+		return (IJobXMLLoaderService)getService(Name.DELEGATING_JOBXML_LOADER_SERVICE);
+	}
+
+	@Override
+	public IBatchArtifactFactory getPreferredArtifactFactory() {
+		return (IBatchArtifactFactory)getService(Name.CONTAINER_ARTIFACT_FACTORY_SERVICE);
+	}
+	
+	@Override
+	public IBatchArtifactFactory getDelegatingArtifactFactory() {
+		return (IBatchArtifactFactory)getService(Name.DELEGATING_ARTIFACT_FACTORY_SERVICE);
+	}
+
+	
+	private class ServiceLoader {
+		
+		
+		volatile IBatchServiceBase service = null;
+		private Name serviceType = null;
+
+		private ServiceLoader(Name name) {
+			this.serviceType = name;
+		}
+
+		private IBatchServiceBase getService() {
+			service = serviceRegistry.get(serviceType);
+			if (service == null) {
+				// Probably don't want to be loading two on two different threads so lock the whole table.
+				synchronized (serviceRegistry) {
+					if (service == null) {
+						service = _loadServiceHelper(serviceType);
+						service.init(batchRuntimeConfig);
+						serviceRegistry.putIfAbsent(serviceType, service);
+					}
+				}
+			}
+			return service;
+		}
+		/**
+		 * Try to load the IGridContainerService given by the className. If it fails
+		 * to load, default to the defaultClass. If the default fails to load, then
+		 * blow out of here with a RuntimeException.
+		 */
+		private IBatchServiceBase _loadServiceHelper(Name serviceType) {
+			IBatchServiceBase service = null;
+			Throwable e = null;
+
+			String className = serviceImplClassNames.get(serviceType);
+			try {
+				if (className != null)
+					service = _loadService(className);
+			} catch (PersistenceException pe) {
+				// Don't rewrap to make it a bit clearer
+				logger.log(Level.SEVERE, "Caught persistence exception which probably means there is an issue initalizing and/or connecting to the RI database");
+				throw pe;
+			} catch (Throwable e1) {
+				e = e1;
+				logger.log(Level.SEVERE, "Could not instantiate service: " + className + " due to exception:" + e);
+				throw new RuntimeException("Could not instantiate service " + className + " due to exception: " + e);
+			}
+
+			if (service == null) {
+				throw new RuntimeException("Instantiate of service=: " + className + " returned null. Aborting...");
+			}
+
+			return service;
+		}
+
+		private IBatchServiceBase _loadService(String className) throws Exception {
+
+			IBatchServiceBase service = null;
+
+			Class cls = Class.forName(className);
+
+			if (cls != null) {
+				Constructor ctor = cls.getConstructor();
+				if (ctor != null) {
+					service = (IBatchServiceBase) ctor.newInstance();
+				} else {
+					throw new Exception("Service class " + className + " should  have a default constructor defined");
+				}
+			} else {
+				throw new Exception("Exception loading Service class " + className + " make sure it exists");
+			}
+
+			return service;
+		}
+	}
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/f7740962/JSR352.Runtime/src/com/ibm/jbatch/container/status/ExecutionStatus.java
----------------------------------------------------------------------
diff --git a/JSR352.Runtime/src/com/ibm/jbatch/container/status/ExecutionStatus.java b/JSR352.Runtime/src/com/ibm/jbatch/container/status/ExecutionStatus.java
new file mode 100755
index 0000000..f4b7e57
--- /dev/null
+++ b/JSR352.Runtime/src/com/ibm/jbatch/container/status/ExecutionStatus.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2012 International Business Machines Corp.
+ * 
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. Licensed under the Apache License, 
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ibm.jbatch.container.status;
+
+public class ExecutionStatus {
+	boolean batchStatusOnly;
+	private ExtendedBatchStatus extendedBatchStatus;
+	private String exitStatus;
+	private String restartOn;
+	
+	// Makes it more explicit that this is not holding an exit status rather than the idea
+	// that there should logically be an exit status whose value happens to be 'null'.
+	public boolean isBatchStatusOnly() {
+		return batchStatusOnly;
+	}
+
+	public ExecutionStatus() {
+		this.batchStatusOnly = true;
+	}
+	
+	public ExecutionStatus(ExtendedBatchStatus extendedBatchStatus) {
+		this();
+		this.extendedBatchStatus = extendedBatchStatus;
+	}
+	
+	public ExecutionStatus(ExtendedBatchStatus extendedBatchStatus, String exitStatus) {
+		super();
+		this.extendedBatchStatus = extendedBatchStatus;
+		this.exitStatus = exitStatus;
+		this.batchStatusOnly = false;
+	}
+	
+	public ExtendedBatchStatus getExtendedBatchStatus() {
+		return extendedBatchStatus;
+	}
+	
+	public void setExtendedBatchStatus(ExtendedBatchStatus extendedBatchStatus) {
+		this.extendedBatchStatus = extendedBatchStatus;
+	}
+	
+	public String getExitStatus() {
+		return exitStatus;
+	}
+	
+	public void setExitStatus(String exitStatus) {
+		this.exitStatus = exitStatus;
+		this.batchStatusOnly = false;
+	}
+	
+	public String getRestartOn() {
+		return restartOn;
+	}
+
+	public void setRestartOn(String restartOn) {
+		this.restartOn = restartOn;
+	}
+	
+	@Override
+	public String toString() {
+		return "BatchStatusOnly?: " + batchStatusOnly + ", extendedBatchStatus = " + extendedBatchStatus.name() +
+				", exitStatus = " + exitStatus + 
+			    ", restartOn = " + restartOn;	
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/f7740962/JSR352.Runtime/src/com/ibm/jbatch/container/status/ExtendedBatchStatus.java
----------------------------------------------------------------------
diff --git a/JSR352.Runtime/src/com/ibm/jbatch/container/status/ExtendedBatchStatus.java b/JSR352.Runtime/src/com/ibm/jbatch/container/status/ExtendedBatchStatus.java
new file mode 100755
index 0000000..ab1f3ee
--- /dev/null
+++ b/JSR352.Runtime/src/com/ibm/jbatch/container/status/ExtendedBatchStatus.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2012 International Business Machines Corp.
+ * 
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. Licensed under the Apache License, 
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ibm.jbatch.container.status;
+
+public enum ExtendedBatchStatus {
+
+	JSL_END, JSL_FAIL, JSL_STOP, NORMAL_COMPLETION, EXCEPTION_THROWN, JOB_OPERATOR_STOPPING, DO_NOT_RUN
+}

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/f7740962/JSR352.Runtime/src/com/ibm/jbatch/container/status/JobStatus.java
----------------------------------------------------------------------
diff --git a/JSR352.Runtime/src/com/ibm/jbatch/container/status/JobStatus.java b/JSR352.Runtime/src/com/ibm/jbatch/container/status/JobStatus.java
new file mode 100755
index 0000000..caa48d7
--- /dev/null
+++ b/JSR352.Runtime/src/com/ibm/jbatch/container/status/JobStatus.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2012 International Business Machines Corp.
+ * 
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. Licensed under the Apache License, 
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+package com.ibm.jbatch.container.status;
+import java.io.Serializable;
+
+import javax.batch.runtime.BatchStatus;
+import javax.batch.runtime.JobInstance;
+
+import com.ibm.jbatch.container.jobinstance.JobInstanceImpl;
+
+public class JobStatus implements Serializable, Cloneable{
+
+    private static final long serialVersionUID = 1L;
+
+    private JobInstance jobInstance;
+
+    private long jobInstanceId;
+
+    private String currentStepId;
+
+    private BatchStatus batchStatus;  // Might be nice to know.
+
+    private String exitStatus;
+
+    // Assume this will be needed.
+    private long latestExecutionId;
+
+    // How many times the status has been updated.
+
+    //TODO - reset to 0?
+    //private int updateCount;
+
+    // TODO - Maybe a job operator would use this?
+    //private int restartCount;
+
+    private String restartOn;
+
+    public JobStatus(long jobInstanceId) {
+        this.jobInstanceId = jobInstanceId;
+    }
+    
+    public JobStatus(JobInstance jobInstance) {
+        this.batchStatus = BatchStatus.STARTING;
+        //this.restartCount = 0;
+       // this.updateCount = 0;  
+        this.jobInstance = jobInstance;
+        this.jobInstanceId = jobInstance.getInstanceId();
+    }
+
+    public long getJobInstanceId() {
+        return this.jobInstanceId;
+    }
+
+    public void setJobInstance(JobInstance jobInstance) {
+        this.jobInstance = jobInstance;
+    }
+    
+    public JobInstanceImpl getJobInstance() {
+        return (JobInstanceImpl)jobInstance;
+    }
+
+    public String getCurrentStepId() {
+        return currentStepId;
+    }
+
+    public void setCurrentStepId(String currentStepId) {
+        this.currentStepId = currentStepId;
+    }
+
+    public BatchStatus getBatchStatus() {
+        return batchStatus;
+    }
+
+    public void setBatchStatus(BatchStatus batchStatus) {
+        this.batchStatus = batchStatus;
+    }
+
+    public long getLatestExecutionId() {
+        return latestExecutionId;
+    }
+
+    public void setLatestExecutionId(long latestExecutionId) {
+        this.latestExecutionId = latestExecutionId;
+    }
+
+    /*
+    public int getUpdateCount() {
+        return updateCount;
+    }
+
+    public void setUpdateCount(int updateCount) {
+        this.updateCount = updateCount;
+    }
+
+    public int getRestartCount() {
+        return restartCount;
+    }
+
+    public void setRestartCount(int restartCount) {
+        this.restartCount = restartCount;
+    }
+    */
+    @Override
+    public String toString() {        
+        
+        StringBuffer buf = new StringBuffer();
+        buf.append(",currentStepId: " + currentStepId);
+        buf.append(",batchStatus: " + batchStatus);
+        buf.append(",latestExecutionId: " + latestExecutionId);
+        buf.append(",restartOn: " + restartOn);
+        return buf.toString();
+    }
+
+    public void setExitStatus(String exitStatus) {
+        this.exitStatus = exitStatus;
+    }
+
+    public String getExitStatus() {
+        return exitStatus;
+    }
+
+    public String getRestartOn() {
+        return restartOn;
+    }
+
+    public void setRestartOn(String restartOn) {
+        this.restartOn = restartOn;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/f7740962/JSR352.Runtime/src/com/ibm/jbatch/container/status/JobStatusKey.java
----------------------------------------------------------------------
diff --git a/JSR352.Runtime/src/com/ibm/jbatch/container/status/JobStatusKey.java b/JSR352.Runtime/src/com/ibm/jbatch/container/status/JobStatusKey.java
new file mode 100755
index 0000000..6554725
--- /dev/null
+++ b/JSR352.Runtime/src/com/ibm/jbatch/container/status/JobStatusKey.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2012 International Business Machines Corp.
+ * 
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. Licensed under the Apache License, 
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+package com.ibm.jbatch.container.status;
+
+public class JobStatusKey {
+	
+	private long jobInstanceId;		
+
+	public JobStatusKey(long jobInstanceId) {
+		this.jobInstanceId = jobInstanceId;
+	}
+	
+	/**
+	 * Note this is the only getter method, to enforce consistency
+	 * in getting the instance ID as key.
+	 * 
+	 * @return jobInstanceId
+	 */
+	public long getDatabaseKey() {
+		return jobInstanceId;
+	}
+	
+	public String toString() {		
+		return "jobInstanceId: " + jobInstanceId;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/f7740962/JSR352.Runtime/src/com/ibm/jbatch/container/status/SplitExecutionStatus.java
----------------------------------------------------------------------
diff --git a/JSR352.Runtime/src/com/ibm/jbatch/container/status/SplitExecutionStatus.java b/JSR352.Runtime/src/com/ibm/jbatch/container/status/SplitExecutionStatus.java
new file mode 100755
index 0000000..b71c8dd
--- /dev/null
+++ b/JSR352.Runtime/src/com/ibm/jbatch/container/status/SplitExecutionStatus.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright 2013 International Business Machines Corp.
+ *
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. Licensed under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ibm.jbatch.container.status;
+
+public class SplitExecutionStatus extends ExecutionStatus {
+	
+	boolean couldMoreThanOneFlowHaveTerminatedJob = false;
+	
+	public SplitExecutionStatus() {
+		super();
+	}
+	
+	public SplitExecutionStatus(ExtendedBatchStatus extendedBatchStatus) {
+		super(extendedBatchStatus);
+	}
+
+	public boolean couldMoreThanOneFlowHaveTerminatedJob() {
+		return couldMoreThanOneFlowHaveTerminatedJob;
+	}
+
+	public void setCouldMoreThanOneFlowHaveTerminatedJob(boolean flag) {
+		this.couldMoreThanOneFlowHaveTerminatedJob = flag;
+	}
+	
+	@Override
+	/* Splits don't have a meaningful exit status at the split level, since we don't elevate
+	 * one flow's exit status above another.
+	 */
+	public String getExitStatus() {
+		return null;
+	}
+	
+	@Override
+	public String toString() {
+		return super.toString() + ", couldMoreThanOneFlowHaveTerminatedJob = " + couldMoreThanOneFlowHaveTerminatedJob; 
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/f7740962/JSR352.Runtime/src/com/ibm/jbatch/container/status/StepStatus.java
----------------------------------------------------------------------
diff --git a/JSR352.Runtime/src/com/ibm/jbatch/container/status/StepStatus.java b/JSR352.Runtime/src/com/ibm/jbatch/container/status/StepStatus.java
new file mode 100755
index 0000000..64b230c
--- /dev/null
+++ b/JSR352.Runtime/src/com/ibm/jbatch/container/status/StepStatus.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2012 International Business Machines Corp.
+ * 
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. Licensed under the Apache License, 
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ibm.jbatch.container.status;
+
+import java.io.ByteArrayInputStream;
+import java.io.Serializable;
+
+import javax.batch.runtime.BatchStatus;
+
+import com.ibm.jbatch.container.exception.BatchContainerRuntimeException;
+import com.ibm.jbatch.container.persistence.PersistentDataWrapper;
+import com.ibm.jbatch.container.util.TCCLObjectInputStream;
+
+public class StepStatus implements Serializable {
+
+    /**
+	 * 
+	 */
+    private static final long serialVersionUID = 1L;
+
+    private long stepExecutionId;
+    private BatchStatus batchStatus;
+    private String exitStatus;
+    private int startCount;
+    private PersistentDataWrapper persistentUserData;
+    private Integer numPartitions;
+    
+    private long lastRunStepExecutionId;
+
+    public StepStatus(long stepExecutionId) {
+        this.startCount = 1;
+        this.stepExecutionId = stepExecutionId;
+        this.lastRunStepExecutionId = stepExecutionId;
+        this.batchStatus = BatchStatus.STARTING;
+    }
+
+    public void setBatchStatus(BatchStatus batchStatus) {
+        this.batchStatus = batchStatus;
+    }
+
+    public BatchStatus getBatchStatus() {
+        return batchStatus;
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer buf = new StringBuffer();
+        buf.append("stepExecutionId: " + stepExecutionId);
+        buf.append(",batchStatus: " + batchStatus);
+        buf.append(",exitStatus: " + exitStatus);
+        buf.append(",startCount: " + startCount);
+        buf.append(",persistentUserData: " + persistentUserData);
+        buf.append(",numPartitions: " + numPartitions);
+        return buf.toString();
+    }
+
+    public long getStepExecutionId() {
+        return stepExecutionId;
+    }
+
+    public int getStartCount() {
+        return startCount;
+    }
+
+    public void incrementStartCount() {
+        startCount++;
+    }
+
+    public void setExitStatus(String exitStatus) {
+        this.exitStatus = exitStatus;
+    }
+
+    public String getExitStatus() {
+        return exitStatus;
+    }
+
+    public void setPersistentUserData(PersistentDataWrapper persistentUserData) {
+        this.persistentUserData = persistentUserData;
+    }
+
+    public Serializable getPersistentUserData() {
+        if (this.persistentUserData != null) {
+            byte[] persistentToken = this.persistentUserData.getPersistentDataBytes();
+            ByteArrayInputStream persistentByteArrayInputStream = new ByteArrayInputStream(persistentToken);
+            TCCLObjectInputStream persistentOIS = null;
+
+            Serializable persistentObject = null;
+
+            try {
+                persistentOIS = new TCCLObjectInputStream(persistentByteArrayInputStream);
+                persistentObject = (Serializable) persistentOIS.readObject();
+            } catch (Exception e) {
+                throw new BatchContainerRuntimeException(e);
+            }
+
+            return persistentObject;
+        } else {
+            return null;
+        }
+    }
+
+    public Integer getNumPartitions() {
+        return numPartitions;
+    }
+
+    public void setNumPartitions(Integer numPartitions) {
+        this.numPartitions = numPartitions;
+    }
+
+    public void setStepExecutionId(long stepExecutionId) {
+        this.stepExecutionId = stepExecutionId;
+        this.lastRunStepExecutionId = this.stepExecutionId;
+    }
+
+    public long getLastRunStepExecutionId() {
+        return lastRunStepExecutionId;
+    }
+
+    public void setLastRunStepExecutionId(long lastRunStepExecutionId) {
+        this.lastRunStepExecutionId = lastRunStepExecutionId;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/f7740962/JSR352.Runtime/src/com/ibm/jbatch/container/status/StepStatusKey.java
----------------------------------------------------------------------
diff --git a/JSR352.Runtime/src/com/ibm/jbatch/container/status/StepStatusKey.java b/JSR352.Runtime/src/com/ibm/jbatch/container/status/StepStatusKey.java
new file mode 100755
index 0000000..9bf7d51
--- /dev/null
+++ b/JSR352.Runtime/src/com/ibm/jbatch/container/status/StepStatusKey.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012 International Business Machines Corp.
+ * 
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. Licensed under the Apache License, 
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+package com.ibm.jbatch.container.status;
+
+public class StepStatusKey {
+	
+	private long _jobInstanceId;
+	
+	/**
+	 * Not public since we don't want the instance id getter public,
+	 * Only for use in trace.
+	 * 
+	 * @return 
+	 */
+	private String getStepId() {
+		return _stepId;
+	}
+
+	private String _stepId;
+	
+	public StepStatusKey(long jobInstanceId, String stepId) {		
+		_jobInstanceId = jobInstanceId;
+		_stepId = stepId;
+	}
+	
+	/**
+	 * Note this is the only getter method, to enforce consistency
+	 * in getting the instance ID as key.
+	 * 
+	 * @return jobInstanceId
+	 */
+	public long getDatabaseKey() {
+		return _jobInstanceId;
+	}
+	
+	public String toString() {		
+	    return Long.toString(_jobInstanceId) + ":" + getStepId();
+	}
+}