package org.oddjob.jobs.structural;
import org.oddjob.arooa.deploy.annotations.ArooaAttribute;
import org.oddjob.framework.OptionallyTransient;
import org.oddjob.framework.SimultaneousStructural;
import org.oddjob.scheduling.ExecutorThrottleType;
import org.oddjob.state.CascadeJob;
import org.oddjob.state.StateOperator;
import org.oddjob.state.AnyActiveStateOp;
/**
* @oddjob.description
*
* A job which executes it's child jobs in parallel.
* <p>
* Once the child jobs are submitted, Oddjob's thread of execution continues
* on out of this job. The state is set to ACTIVE and will continue to
* change depending on the state of the child Jobs. The <code>join</code>
* property can be used to hold the thread of execution until the
* submitted jobs have finished executing - but it's use is discouraged.
* See the property documentation below for more information.
*
* The state of job, including its modification by the
* <code>stateOperator</code> property is identical to {@link SequentialJob}
* and is well documented there. Likewise with the transient property.
*
* @oddjob.example
*
* Two jobs running in parallel. Note that the order of execution of the
* two child jobs is not predictable.
*
* {@oddjob.xml.resource org/oddjob/jobs/structural/SimpleParallelExample.xml}
*
* @oddjob.example
*
* Two services started in parallel. This might be quite useful if the
* services took a long time to start - maybe because they loaded a lot
* of data into a cache for instance.
*
* {@oddjob.xml.resource org/oddjob/jobs/structural/ParallelServicesExample.xml}
*
* The {@link CascadeJob} will execute the final job only once both services
* have started, and it will continue be in a STARTED after execution has
* completed.
* <p>
* Adding a SERVICES stateOperator property will mean that parallel is
* COMPLETE once the services have started and so the whole cascade shows
* as complete.
*
* {@oddjob.xml.resource org/oddjob/jobs/structural/ParallelServicesExample2.xml}
*
* @oddjob.example
*
* Examples elsewhere.
* <ul>
* <li>{@link ExecutorThrottleType} has an example of limiting the number
* of concurrently executing jobs.</li>
* </ul>
*
*
* @author Rob Gordon
*/
public class ParallelJob extends SimultaneousStructural
implements OptionallyTransient {
private static final long serialVersionUID = 2009031800L;
/**
* @oddjob.property
* @oddjob.description Should the execution thread of this job wait
* for the execution threads of the child jobs.
* <p>
* This property
* re-introduces the default behaviour of parallel before version 1.0.
* Behaviour was changed to encourage the use of event driven
* configuration that didn't cause a thread to wait by using
* {@link org.oddjob.state.CascadeJob} or
* {@link org.oddjob.scheduling.Trigger}.
* <p>
* There are situations where this is really convenient as otherwise
* large reworking of the configuration is required. If possible -
* it is better practice to try and use the job state.
*
* @oddjob.required No. Defaults to false
*/
private volatile boolean join;
/**
* @oddjob.property transient
* @oddjob.description Is this job transient. If true state will not
* be persisted.
* @oddjob.required No, default is false.
*
*/
private volatile boolean _transient;
/**
* @oddjob.property stateOperator
* @oddjob.description Set the way the children's state is
* evaluated and reflected by the parent. Values can be WORST,
* ACTIVE, or SERVICES.
* @oddjob.required No, default is ACTIVE.
*
* @param stateOperator The state operator to be applied to children's
* states to derive our state.
*/
@ArooaAttribute
public void setStateOperator(StateOperator stateOperator) {
this.structuralState.setStateOperator(stateOperator);
}
/**
* Getter for State Operator.
*
* @return
*/
public StateOperator getStateOperator() {
return this.structuralState.getStateOperator();
}
@Override
protected StateOperator getInitialStateOp() {
return new AnyActiveStateOp();
}
@Override
public boolean isJoin() {
return join;
}
public void setJoin(boolean join) {
this.join = join;
}
/*
* (non-Javadoc)
* @see org.oddjob.framework.OptionallyTransient#isTransient()
*/
public boolean isTransient() {
return _transient;
}
public void setTransient(boolean _transient) {
this._transient = _transient;
}
}