1 package org
.argeo
.slc
.core
.execution
.generator
;
6 import org
.apache
.commons
.logging
.Log
;
7 import org
.apache
.commons
.logging
.LogFactory
;
8 import org
.argeo
.slc
.SlcException
;
9 import org
.argeo
.slc
.core
.execution
.DefaultExecutionSpec
;
10 import org
.argeo
.slc
.execution
.ExecutionContext
;
11 import org
.argeo
.slc
.execution
.ExecutionFlow
;
12 import org
.argeo
.slc
.execution
.ExecutionSpec
;
13 import org
.springframework
.context
.ApplicationContext
;
14 import org
.springframework
.context
.ApplicationContextAware
;
17 * Execution Flow calling a list of <code>Runnable</code> (identified by their bean
18 * name in the Spring Application Context) after configuring the Execution
19 * context and a Map potentially shared by the called <code>Runnable</code>
22 public class RunnableCallFlow
implements ExecutionFlow
, ApplicationContextAware
{
24 private final static Log log
= LogFactory
.getLog(RunnableCallFlow
.class);
27 * Key in the execution context for the index of the call (e.g. 0
28 * for the first runnable called, ...)
30 public final static String VAR_CALL_INDEX
= "slcVar.runnableCallFlow.callIndex";
33 * Name of the flow. Also bean name
43 * Whether an exception in a <code>Runnable</code> shall
44 * stop the execution of the flow
46 private Boolean failOnError
= true;
49 * List of <code>Runnable</code> to call, with bean name, execution variables and
52 private List
<RunnableCall
> runnableCalls
;
55 * Map potentially referenced by called flows. Updated with
56 * the context values of a Runnable before calling it.
58 private Map
<String
, Object
> sharedContextValuesMap
;
61 * ExecutionSpec of the flow. Does not contain any
64 private ExecutionSpec executionSpec
= new DefaultExecutionSpec();
67 * Reference to the ExecutionContext
69 private ExecutionContext executionContext
;
72 * Reference to the Spring <code>ApplicationContext</code>.
73 * Set via <code>setApplicationContext</code>, the class implementing
74 * <code>ApplicationContextAware</code>
76 private ApplicationContext applicationContext
;
79 * Runs a <code>Runnable</code> after configuring the Execution Context
80 * and <code>sharedContextValuesMap</code>
81 * @param runnable the <code>Runnable</code> to call
82 * @param executionVariables the variables to add to the <code>ExecutionContext</code>
83 * @param contextValues the variables to add to <code>sharedContextValuesMap</code>
84 * @param callIndex index of the call (0 for the first called <code>Runnable</code>)
85 * set as variable of the <code>ExecutionContext</code>
87 private void run(Runnable runnable
, Map
<String
, Object
> executionVariables
, Map
<String
, Object
> contextValues
, int callIndex
) {
88 // add all variables to the Execution Context
89 for(Map
.Entry
<String
,Object
> entry
: executionVariables
.entrySet()) {
90 executionContext
.setVariable(entry
.getKey(), entry
.getValue());
93 // add call Index Variable
94 executionContext
.setVariable(VAR_CALL_INDEX
, callIndex
);
96 // clear sharedContextValues and add all values of contextValues
97 if(sharedContextValuesMap
!= null) {
98 sharedContextValuesMap
.clear();
99 sharedContextValuesMap
.putAll(contextValues
);
102 // then run the runnable
108 * For each <code>RunnableCall</code>, the corresponding flow
109 * is retrieved from the Spring Application Context, the
110 * <code>ExecutionContext</code> and <code>sharedContextValuesMap</code>
111 * are configured and the <code>Runnable</code> is called.
114 if (applicationContext
== null) {
115 throw new SlcException("No ApplicationContext defined");
119 for(int callIndex
= 0; callIndex
< runnableCalls
.size(); ++callIndex
) {
120 RunnableCall runnableCall
= runnableCalls
.get(callIndex
);
121 Object bean
= applicationContext
.getBean(runnableCall
.getBeanName(), Runnable
.class);
122 if(log
.isDebugEnabled())
123 log
.debug("Running flow '" + runnableCall
.getBeanName() + "'");
124 run((Runnable
)bean
, runnableCall
.getExecutionVariables(), runnableCall
.getContextValues(), callIndex
);
126 } catch (RuntimeException e
) {
130 log
.error("Execution flow failed,"
131 + " but process did not fail"
132 + " because failOnError property"
133 + " is set to false: " + e
);
134 if (log
.isTraceEnabled())
140 public ExecutionSpec
getExecutionSpec() {
141 return executionSpec
;
144 public String
getName() {
148 public Object
getParameter(String key
) {
149 throw new SlcException("RunnableCallFlow have no parameters");
152 public String
getPath() {
156 public Boolean
isSetAsParameter(String key
) {
157 // The ExecutionSpec having no attribute,
158 // always return false
162 public void setName(String name
) {
166 public void setPath(String path
) {
170 public void setExecutionContext(ExecutionContext executionContext
) {
171 this.executionContext
= executionContext
;
174 public void setRunnableCalls(List
<RunnableCall
> runnableCalls
) {
175 this.runnableCalls
= runnableCalls
;
178 public void setApplicationContext(ApplicationContext applicationContext
) {
179 this.applicationContext
= applicationContext
;
182 public void setSharedContextValuesMap(Map
<String
, Object
> contextValues
) {
183 this.sharedContextValuesMap
= contextValues
;
186 public void setFailOnError(Boolean failOnError
) {
187 this.failOnError
= failOnError
;