org.refcodes.jobbus.AbstractJobBus Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of refcodes-jobbus Show documentation
Show all versions of refcodes-jobbus Show documentation
Artifact providing command pattern based job-bus functionality.
// /////////////////////////////////////////////////////////////////////////////
// REFCODES.ORG
// =============================================================================
// This code is copyright (c) by Siegfried Steiner, Munich, Germany and licensed
// under the following (see "http://en.wikipedia.org/wiki/Multi-licensing")
// licenses:
// =============================================================================
// GNU General Public License, v3.0 ("http://www.gnu.org/licenses/gpl-3.0.html")
// together with the GPL linking exception applied; as being applied by the GNU
// Classpath ("http://www.gnu.org/software/classpath/license.html")
// =============================================================================
// Apache License, v2.0 ("http://www.apache.org/licenses/TEXT-2.0")
// =============================================================================
// Please contact the copyright holding author(s) of the software artifacts in
// question for licensing issues not being covered by the above listed licenses,
// also regarding commercial licensing models or regarding the compatibility
// with other open source licenses.
// /////////////////////////////////////////////////////////////////////////////
package org.refcodes.jobbus;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutorService;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.refcodes.command.NoExceptionAvailableRuntimeException;
import org.refcodes.command.NoResultAvailableRuntimeException;
import org.refcodes.command.NotYetExecutedRuntimeException;
import org.refcodes.command.Undoable;
import org.refcodes.component.Flushable;
import org.refcodes.component.HandleGenerator;
import org.refcodes.component.HandleTimeoutRuntimeException;
import org.refcodes.component.ProgressAccessor;
import org.refcodes.component.UnknownHandleRuntimeException;
import org.refcodes.component.UnsupportedHandleOperationRuntimeException;
import org.refcodes.controlflow.ControlFlowUtility;
import org.refcodes.controlflow.RetryTimeout;
import org.refcodes.data.RetryLoopCount;
import org.refcodes.data.SleepLoopTime;
import org.refcodes.exception.ExceptionUtility;
import org.refcodes.mixin.Resetable;
/**
* The {@link AbstractJobBus} implements the {@link JobBus} interface.
*
* @param The context type to use, can by any component, service or POJO.
* @param The handle type used to reference a job.
*/
public abstract class AbstractJobBus implements JobBus {
// /////////////////////////////////////////////////////////////////////////
// STATICS:
// /////////////////////////////////////////////////////////////////////////
private static Logger LOGGER = Logger.getLogger( AbstractJobBus.class.getName() );
// /////////////////////////////////////////////////////////////////////////
// VARIABLES:
// /////////////////////////////////////////////////////////////////////////
private final Map> _handleToJobDescriptors = new WeakHashMap>();
private HandleGenerator _handleGenerator;
final private CTX _context;
private ExecutorService _executorService;
// /////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS:
// /////////////////////////////////////////////////////////////////////////
/**
* Instantiates the {@link AbstractJobBus} with the provided context and the
* provided {@link HandleGenerator}. It is up to you which context (service,
* {@link org.refcodes.component.Component}, POJO) you want to provide to a
* job ({@link Undoable}) when being executed. Also you can provide any
* {@link HandleGenerator} you thing useful when creating handles. It is up
* to your {@link HandleGenerator} to generate unique handle objects. The
* {@link JobBusDirectory} actually uses a {@link String} objects generating
* {@link HandleGenerator}. Make sure your handles implement the
* {@link #hashCode()} and {@link #equals(Object)} methods as of their
* method contracts as them handles will be used in collections such as
* {@link HashMap} data structures.
*
* @param aContext The context which is passed to the job ({@link Undoable})
* instances when being executed.
* @param aHandleGenerator The {@link HandleGenerator} to be used when
* generating unique handle objects.
*/
public AbstractJobBus( CTX aContext, HandleGenerator aHandleGenerator ) {
this( aContext, aHandleGenerator, null );
}
/**
* Instantiates the {@link AbstractJobBus} with the provided context and the
* provided {@link HandleGenerator}. It is up to you which context (service,
* {@link org.refcodes.component.Component}, POJO) you want to provide to a
* job ({@link Undoable}) when being executed. Also you can provide any
* {@link HandleGenerator} you thing useful when creating handles. It is up
* to your {@link HandleGenerator} to generate unique handle objects. The
* {@link JobBusDirectory} actually uses a {@link String} objects generating
* {@link HandleGenerator}. Make sure your handles implement the
* {@link #hashCode()} and {@link #equals(Object)} methods as of their
* method contracts as them handles will be used in collections such as
* {@link HashMap} data structures.
*
* @param aContext The context which is passed to the job ({@link Undoable})
* instances when being executed.
* @param aHandleGenerator The {@link HandleGenerator} to be used when
* generating unique handle objects.
* @param aExecutorService The {@link ExecutorService} to be used, when null
* then an {@link ExecutorService} something like
* {@link ControlFlowUtility#createCachedExecutorService(boolean)} is
* then retrieved.
*/
public AbstractJobBus( CTX aContext, HandleGenerator aHandleGenerator, ExecutorService aExecutorService ) {
assert (aHandleGenerator != null);
assert (aContext != null);
_handleGenerator = aHandleGenerator;
_context = aContext;
if ( aExecutorService == null ) {
_executorService = ControlFlowUtility.createCachedExecutorService( true );
}
else {
_executorService = ControlFlowUtility.toManagedExecutorService( aExecutorService );
}
}
// /////////////////////////////////////////////////////////////////////////
// METHODS:
// /////////////////////////////////////////////////////////////////////////
/**
* {@inheritDoc}
*/
@Override
public H execute( final Undoable aJob ) {
assert (aJob != null);
H theHandle = _handleGenerator.next();
start( (Undoable) aJob, theHandle );
return theHandle;
}
/**
* {@inheritDoc}
*/
@Override
public void execute( Undoable aJob, BiConsumer aResultConsumer ) {
assert (aJob != null);
assert (aResultConsumer != null);
invoke( aJob, aResultConsumer );
}
/**
* {@inheritDoc}
*/
@Override
public void execute( Undoable aJob, Consumer aResultConsumer ) {
assert (aJob != null);
assert (aResultConsumer != null);
invoke( aJob, aResultConsumer );
}
/**
* Gets the exception.
*
* @param the element type
* @param aHandle the handle
*
* @return the exception
*
* @throws UnknownHandleRuntimeException the unknown handle runtime
* exception
* @throws NotYetExecutedRuntimeException the not yet executed runtime
* exception
* @throws NoExceptionAvailableRuntimeException the no exception available
* runtime exception
*/
@SuppressWarnings("unchecked")
@Override
public E getException( H aHandle ) throws UnknownHandleRuntimeException, NotYetExecutedRuntimeException, NoExceptionAvailableRuntimeException {
JobDescriptor> theJobDescriptor = _handleToJobDescriptors.get( aHandle );
if ( theJobDescriptor == null ) {
throw new UnknownHandleRuntimeException( aHandle, "The given handle is not known by this job-bus." );
}
if ( !theJobDescriptor.isExecuted() ) {
throw new NotYetExecutedRuntimeException( theJobDescriptor.getJob(), "The given job has not finished execution yet." );
}
if ( theJobDescriptor.getException() == null ) {
throw new NoExceptionAvailableRuntimeException( theJobDescriptor.getJob(), "The given job has no execption." );
}
return (E) theJobDescriptor.getException();
}
/**
* Gets the result.
*
* @param the generic type
* @param aHandle the handle
*
* @return the result
*
* @throws UnknownHandleRuntimeException the unknown handle runtime
* exception
* @throws NotYetExecutedRuntimeException the not yet executed runtime
* exception
* @throws NoResultAvailableRuntimeException the no result available runtime
* exception
*/
@SuppressWarnings("unchecked")
@Override
public RET getResult( H aHandle ) throws UnknownHandleRuntimeException, NotYetExecutedRuntimeException, NoResultAvailableRuntimeException {
JobDescriptor> theJobDescriptor = _handleToJobDescriptors.get( aHandle );
if ( theJobDescriptor == null ) {
throw new UnknownHandleRuntimeException( aHandle, "The given handle is not known by this job-bus." );
}
if ( !theJobDescriptor.isExecuted() ) {
throw new NotYetExecutedRuntimeException( theJobDescriptor.getJob(), "The given job has not finished execution yet." );
}
if ( theJobDescriptor.getExecutionStatus() != ExecutionStatus.RESULT ) {
throw new NoResultAvailableRuntimeException( theJobDescriptor.getJob(), "The given job has no execption." );
}
return (RET) theJobDescriptor.getResult();
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasException( H aHandle ) throws UnknownHandleRuntimeException, NotYetExecutedRuntimeException {
JobDescriptor> theJobDescriptor = _handleToJobDescriptors.get( aHandle );
if ( theJobDescriptor == null ) {
throw new UnknownHandleRuntimeException( aHandle, "The given handle is not known by this job-bus." );
}
if ( !theJobDescriptor.isExecuted() ) {
throw new NotYetExecutedRuntimeException( theJobDescriptor.getJob(), "The given job has not finished execution yet." );
}
return (theJobDescriptor.getException() != null);
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasResult( H aHandle ) throws UnknownHandleRuntimeException, NotYetExecutedRuntimeException {
JobDescriptor> theJobDescriptor = _handleToJobDescriptors.get( aHandle );
if ( theJobDescriptor == null ) {
throw new UnknownHandleRuntimeException( aHandle, "The given handle is not known by this job-bus." );
}
if ( !theJobDescriptor.isExecuted() ) {
throw new NotYetExecutedRuntimeException( theJobDescriptor.getJob(), "The given job has not finished execution yet." );
}
return theJobDescriptor.getExecutionStatus() == ExecutionStatus.RESULT;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isExecuted( H aHandle ) throws UnknownHandleRuntimeException {
JobDescriptor> theJobDescriptor = _handleToJobDescriptors.get( aHandle );
if ( theJobDescriptor == null ) {
throw new UnknownHandleRuntimeException( aHandle, "The given handle is not known by this job-bus." );
}
return theJobDescriptor.isExecuted();
}
/**
* {@inheritDoc}
*/
@Override
public void waitForExecution( H aHandle ) throws UnknownHandleRuntimeException {
if ( !hasHandle( aHandle ) ) {
throw new UnknownHandleRuntimeException( aHandle, "The given handle is not known by this job-bus." );
}
try {
// -----------------------------------------------------------------
// In case we miss the 'notifyAll()' call as it might have occurred
// in the very short time slot between testing for execution finish
// and waiting to be interrupted, we periodically check if the job
// has been executed in order to avoid endless waiting. Max wait
// time in case of a missed notify per loop is the
// RefcodesConstants#MIN_CODE_LOOP_SLEEP_TIME_IN_MS
// -----------------------------------------------------------------
while ( !isExecuted( aHandle ) ) {
synchronized ( aHandle ) {
aHandle.wait( SleepLoopTime.MIN.getTimeMillis() );
}
}
}
catch ( InterruptedException ignored ) {}
}
/**
* {@inheritDoc}
*/
@Override
public void waitForExecution( H aHandle, long aTimeoutMillis ) throws UnknownHandleRuntimeException, HandleTimeoutRuntimeException {
if ( !hasHandle( aHandle ) ) {
throw new UnknownHandleRuntimeException( aHandle, "The given handle is not known by this job-bus." );
}
// -----------------------------------------------------------------
// In case we miss the 'notifyAll()' call as it might have occurred
// in the very short time slot between testing for execution finish
// and waiting to be interrupted, we periodically check if the job
// has been executed in order to avoid endless waiting. Max wait
// time in case of a missed notify per loop is the
// RefcodesConstants#MIN_CODE_LOOP_SLEEP_TIME_IN_MS
// -----------------------------------------------------------------
RetryTimeout theRetryTimeout = new RetryTimeout( aTimeoutMillis, RetryLoopCount.NORM_NUM_RETRY_LOOPS.getValue() );
while ( !isExecuted( aHandle ) && theRetryTimeout.hasNextRetry() ) {
theRetryTimeout.nextRetry( aHandle );
}
if ( !isExecuted( aHandle ) ) {
throw new HandleTimeoutRuntimeException( aHandle, "Execution of the command referenced by the given handle did not terminate in the given amount of <" + aTimeoutMillis + "> ms, aborting wait loop." );
}
}
/**
* {@inheritDoc}
*/
@Override
public , RET> RET getResult( final JOB aJob ) throws NoResultAvailableRuntimeException {
// ---------------------------------------------------------------------
// We don't do it the easy way (as below in comments) because we might
// want to retrieve the state of all running jobs from somewhere else,
// i.e. even this synchronously executing job must be available in the
// job-bus itself. Therefore we go for handle first.
// ---------------------------------------------------------------------
// aJob.execute( serviceBus );
// return aJob.getResult();
// ---------------------------------------------------------------------
H theHandle = _handleGenerator.next();
final JobDescriptor theJobDescriptor = start( aJob, theHandle );
if ( theJobDescriptor == null ) {
throw new IllegalStateException( "The job bis encountered an illegal state as a just created handle for executing a job is not konwn by the job-bus any more." );
}
waitForExecution( theHandle );
if ( theJobDescriptor.getExecutionStatus() == ExecutionStatus.EXCEPTION ) {
throw new NoResultAvailableRuntimeException( theJobDescriptor.getJob(), "No result available, the job terminated with an exception!", theJobDescriptor.getException() );
}
if ( theJobDescriptor.getExecutionStatus() == ExecutionStatus.RESULT ) {
return theJobDescriptor.getResult();
}
throw new NoResultAvailableRuntimeException( aJob, "The job for which a result is excpected does not deliver a result, it is a \"void\" job." );
}
/**
* {@inheritDoc}
*/
@Override
public , RET> RET getResult( JOB aJob, long aTimeoutMillis ) throws NoResultAvailableRuntimeException, HandleTimeoutRuntimeException {
// ---------------------------------------------------------------------
// We don't do it the easy way (as below in comments) because we might
// want to retrieve the state of all running jobs from somewhere else,
// i.e. even this synchronously executing job must be available in the
// job-bus itself. Therefore we go for handle first.
// ---------------------------------------------------------------------
// aJob.execute( serviceBus );
// return aJob.getResult();
// ---------------------------------------------------------------------
H theHandle = _handleGenerator.next();
final JobDescriptor theJobDescriptor = start( aJob, theHandle );
if ( theJobDescriptor == null ) {
throw new IllegalStateException( "The job bis encountered an illegal state as a just created handle for executing a job is not konwn by the job-bus any more." );
}
waitForExecution( theHandle, aTimeoutMillis );
if ( theJobDescriptor.getExecutionStatus() == ExecutionStatus.EXCEPTION ) {
throw new NoResultAvailableRuntimeException( theJobDescriptor.getJob(), "No result available, the job terminated with an exception!", theJobDescriptor.getException() );
}
if ( theJobDescriptor.getExecutionStatus() == ExecutionStatus.RESULT ) {
return theJobDescriptor.getResult();
}
throw new NoResultAvailableRuntimeException( aJob, "The job for which a result is excpected does not deliver a result, it is a \"void\" job." );
}
// /////////////////////////////////////////////////////////////////////////
// JOB-BUS:
// /////////////////////////////////////////////////////////////////////////
/**
* {@inheritDoc}
*/
@Override
public boolean hasHandle( H aHandle ) {
return _handleToJobDescriptors.containsKey( aHandle );
}
/**
* {@inheritDoc}
*/
@Override
public Undoable lookupHandle( H aHandle ) throws UnknownHandleRuntimeException {
JobDescriptor> theJobDescriptor = _handleToJobDescriptors.get( aHandle );
if ( theJobDescriptor == null ) {
throw new UnknownHandleRuntimeException( aHandle, "The given handle is not known by this job-bus." );
}
return theJobDescriptor.getJob();
}
/**
* {@inheritDoc}
*/
@Override
public Undoable removeHandle( H aHandle ) throws UnknownHandleRuntimeException {
JobDescriptor> theJobDescriptor = _handleToJobDescriptors.remove( aHandle );
if ( theJobDescriptor == null ) {
throw new UnknownHandleRuntimeException( aHandle, "The given handle is not known by this job-bus." );
}
return theJobDescriptor.getJob();
}
// /////////////////////////////////////////////////////////////////////////
// JOB:
// /////////////////////////////////////////////////////////////////////////
/**
* {@inheritDoc}
*/
@Override
public boolean hasProgress( H aHandle ) throws UnknownHandleRuntimeException {
Undoable theJob = getJob( aHandle );
return (theJob instanceof ProgressAccessor);
}
/**
* {@inheritDoc}
*/
@Override
public float getProgress( H aHandle ) throws UnsupportedHandleOperationRuntimeException, UnknownHandleRuntimeException {
Undoable theJob = getJob( aHandle );
if ( !(theJob instanceof ProgressAccessor) ) {
throw new UnsupportedHandleOperationRuntimeException( aHandle, "The operation is not known by the job referenced by the given handle." );
}
return ((ProgressAccessor) theJob).getProgress();
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasReset( H aHandle ) throws UnknownHandleRuntimeException {
Undoable theJob = getJob( aHandle );
return (theJob instanceof Resetable);
}
/**
* {@inheritDoc}
*/
@Override
public void reset( H aHandle ) throws UnknownHandleRuntimeException, UnsupportedHandleOperationRuntimeException {
Undoable theJob = getJob( aHandle );
if ( !(theJob instanceof Resetable) ) {
throw new UnsupportedHandleOperationRuntimeException( aHandle, "The operation is not known by the job referenced by the given handle." );
}
((Resetable) theJob).reset();
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasFlush( H aHandle ) throws UnknownHandleRuntimeException {
Undoable theJob = getJob( aHandle );
return (theJob instanceof Flushable);
}
/**
* {@inheritDoc}
*/
@Override
public void flush( H aHandle ) throws IOException, UnknownHandleRuntimeException, UnsupportedHandleOperationRuntimeException {
Undoable theJob = getJob( aHandle );
if ( !(theJob instanceof Flushable) ) {
throw new UnsupportedHandleOperationRuntimeException( aHandle, "The operation is not known by the job referenced by the given handle." );
}
((Flushable) theJob).flush();
}
// /////////////////////////////////////////////////////////////////////////
// HOOKS:
// /////////////////////////////////////////////////////////////////////////
/**
* Retrieves the list of objects referenced by the handles.
*
* @return A collection with the objects referenced by handles.
*/
protected Collection> handleReferences() {
List> theJobList = new ArrayList>();
Collection> theJobDescriptorCollection = _handleToJobDescriptors.values();
for ( JobDescriptor> eJobDescriptor : theJobDescriptorCollection ) {
theJobList.add( eJobDescriptor.getJob() );
}
return theJobList;
}
/**
* Returns the set of handles managed by this implementation.
*
* @return The set containing all currently managed handles.
*/
protected Set handles() {
return new HashSet( _handleToJobDescriptors.keySet() );
}
/**
* Gets the job.
*
* @param aHandle the handle
*
* @return the job
*
* @throws UnknownHandleRuntimeException the unknown handle runtime
* exception
*/
protected Undoable getJob( H aHandle ) throws UnknownHandleRuntimeException {
JobDescriptor> theJobDescriptor = _handleToJobDescriptors.get( aHandle );
if ( theJobDescriptor == null ) {
throw new UnknownHandleRuntimeException( aHandle, "The given handle is not known by this job-bus." );
}
return theJobDescriptor.getJob();
}
// HELPER:
/**
* Links the given handle to the given {@link Undoable} (Job) which is
* executed.
*
* @param the generic type
* @param the generic type
* @param aJob The {@link Undoable} (job) to be executed.
* @param aHandle The handle to which the {@link Undoable} (job) is to be
* referenced.
*
* @return The {@link JobDescriptor} describing the {@link Undoable}
* instance's execution status.
*/
private , RET> JobDescriptor start( final JOB aJob, H aHandle ) {
final JobDescriptor theJobDescriptor = new JobDescriptor( aJob );
_handleToJobDescriptors.put( aHandle, theJobDescriptor );
Runnable theJobRunnable = new Runnable() {
/**
* {@inheritDoc}
*/
@Override
public void run() {
try {
theJobDescriptor.setResult( aJob.execute( _context ) );
}
catch ( Exception e ) {
theJobDescriptor.setException( e );
}
theJobDescriptor.setExecuted( true );
synchronized ( aHandle ) {
aHandle.notifyAll();
}
}
};
_executorService.execute( theJobRunnable );
// Thread theJobThread = new Thread( theJobRunnable );
// theJobThread.setPriority( Thread.NORM_PRIORITY );
// theJobThread.start();
return theJobDescriptor;
}
/**
* Links the given handle to the given {@link Undoable} (Job) which is
* executed.
*
* @param the element type
* @param the generic type
* @param the generic type
* @param aJob The {@link Undoable} (job) to be executed.
* @param aResultConsumer the result consumer
*
* @return The {@link JobDescriptor} describing the {@link Undoable}
* instance's execution status.
*/
private , RET> void invoke( final Undoable aJob, final BiConsumer aResultConsumer ) {
Runnable theJobRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
try {
aResultConsumer.accept( aJob.execute( _context ), null );
}
catch ( Exception e ) {
aResultConsumer.accept( null, (E) e );
}
}
};
_executorService.execute( theJobRunnable );
// Thread theJobThread = new Thread( theJobRunnable );
// theJobThread.setPriority( Thread.NORM_PRIORITY );
// theJobThread.start();
}
/**
* Links the given handle to the given {@link Undoable} (Job) which is
* executed.
*
* @param the element type
* @param the generic type
* @param the generic type
* @param aJob The {@link Undoable} (job) to be executed.
* @param aResultConsumer the result consumer
*
* @return The {@link JobDescriptor} describing the {@link Undoable}
* instance's execution status.
*/
private , RET> void invoke( final Undoable aJob, final Consumer aResultConsumer ) {
Runnable theJobRunnable = new Runnable() {
/**
* {@inheritDoc}
*/
@Override
public void run() {
try {
aResultConsumer.accept( aJob.execute( _context ) );
}
catch ( Exception e ) {
LOGGER.log( Level.WARNING, "Daemon exception occured: " + ExceptionUtility.toMessage( e ), e );
}
}
};
_executorService.execute( theJobRunnable );
// Thread theJobThread = new Thread( theJobRunnable );
// theJobThread.setPriority( Thread.NORM_PRIORITY );
// theJobThread.start();
}
// /////////////////////////////////////////////////////////////////////////
// INNER CLASSES:
// /////////////////////////////////////////////////////////////////////////
/**
* Defines the status of a {@link JobDescriptor}'s execution status:.
*/
private enum ExecutionStatus {
VOID,
RESULT,
EXCEPTION
}
/**
* This job descriptor is needed to hold all information concerning a job
* executed and managed by handle.
*
* @param The type of the return value-
*/
private class JobDescriptor {
private Undoable _job;
private RET _result = null;
private Exception _exception = null;
private boolean _isExecuted = false;
private ExecutionStatus _executionStatus = ExecutionStatus.VOID;
/**
* Constructs the job descriptor.
*
* @param aJob The job associated to the job descriptor.
*/
public JobDescriptor( Undoable aJob ) {
assert (aJob != null);
_job = aJob;
}
/**
* Returns the job associated with this job descriptor.
*
* @return The job associated with this job descriptor.
*/
public Undoable getJob() {
return _job;
}
/**
* Sets the result which was returned after job execution.
*
* @param aResult The result to be set.
*/
public void setResult( RET aResult ) {
_result = aResult;
_executionStatus = ExecutionStatus.RESULT;
}
/**
* Retrieves the result which was returned during job execution (if
* any).
*
* @return The result being set or null.
*/
public RET getResult() {
return _result;
}
/**
* Returns {@link ExecutionStatus#RESULT} in case a result has been set,
* {@link ExecutionStatus#EXCEPTION} in case of an exceptional state and
* {@link ExecutionStatus#VOID} if neither of both is the case.
*
* @return True in case a result has been set.
*/
public ExecutionStatus getExecutionStatus() {
return _executionStatus;
}
/**
* Sets the exception which was caught during job execution.
*
* @param e The exception to be set.
*/
public void setException( Exception e ) {
_exception = e;
_executionStatus = ExecutionStatus.EXCEPTION;
}
/**
* Retrieves the exception which was caught during job execution (if
* any).
*
* @return The exception being set or null.
*/
public Exception getException() {
return _exception;
}
/**
* Returns true if the job has been executed.
*
* @return True if it has been executed
*/
public boolean isExecuted() {
return _isExecuted;
}
/**
* Sets the execution state for the according job.
*
* @param isExecuted The executed status for the according job.
*/
public void setExecuted( boolean isExecuted ) {
_isExecuted = isExecuted;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy