1
2
3
4
5
6
7
8
9
10
11 package org.mule.module.jbpm;
12
13 import org.mule.api.lifecycle.Disposable;
14 import org.mule.api.lifecycle.Initialisable;
15 import org.mule.module.bpm.BPMS;
16 import org.mule.module.bpm.MessageService;
17 import org.mule.util.IOUtils;
18
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.util.Map;
22 import java.util.Properties;
23 import java.util.Set;
24
25 import org.jbpm.api.Configuration;
26 import org.jbpm.api.Execution;
27 import org.jbpm.api.ProcessEngine;
28 import org.jbpm.api.ProcessInstance;
29 import org.jbpm.api.task.Task;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33
34
35
36 public class Jbpm implements BPMS, Initialisable, Disposable
37 {
38
39
40
41 protected ProcessEngine processEngine = null;
42
43
44
45
46 private String configurationResource;
47
48
49
50
51 private Properties processDefinitions;
52
53
54
55
56 private String name;
57
58
59
60
61
62 protected boolean containerManaged = true;
63
64 public static final String PROCESS_ENDED = "Process has ended";
65
66
67
68
69
70
71 public static final int PROCESS_CREATION_WAIT = 3000;
72
73 protected static final Logger log = LoggerFactory.getLogger(Jbpm.class);
74
75
76
77
78
79
80
81
82 public Jbpm()
83 {
84
85 }
86
87
88
89
90
91
92 public Jbpm(String configurationResource, Properties processDefinitions)
93 {
94 this.configurationResource = configurationResource;
95 this.processDefinitions = processDefinitions;
96 }
97
98
99
100
101
102
103
104 public Jbpm(ProcessEngine processEngine, Properties processDefinitions)
105 {
106 this.processEngine = processEngine;
107 this.processDefinitions = processDefinitions;
108 }
109
110 @Override
111 public void initialise()
112 {
113 if (processEngine == null)
114 {
115 Configuration config = new Configuration();
116 if (configurationResource != null)
117 {
118 config.setResource(configurationResource);
119 }
120 setProcessEngine(config.buildProcessEngine());
121 containerManaged = false;
122 }
123 if (processDefinitions != null)
124 {
125 for (Object def : processDefinitions.values())
126 {
127 try
128 {
129 deployProcess((String) def);
130 }
131 catch (IOException e)
132 {
133 log.error("Unable to deploy process definition: " + e.getMessage());
134 }
135 }
136 }
137 }
138
139 @Override
140 public void dispose()
141 {
142 if (!containerManaged && processEngine != null)
143 {
144 processEngine.close();
145 processEngine = null;
146 }
147 }
148
149 @Override
150 public void setMessageService(MessageService msgService)
151 {
152 MuleMessageService serviceProxy = processEngine.get(MuleMessageService.class);
153 serviceProxy.setMessageService(msgService);
154 }
155
156
157
158
159
160
161
162
163
164
165 public Object startProcess(Object processDefinitionKey) throws Exception
166 {
167 return startProcess(processDefinitionKey, null, null);
168 }
169
170
171
172
173
174
175 @Override
176 public Object startProcess(Object processDefinitionKey, Object signalName, Map variables) throws Exception
177 {
178 ProcessInstance processInstance =
179 processEngine.getExecutionService().startProcessInstanceByKey((String) processDefinitionKey, variables);
180
181 if (processInstance == null)
182 {
183 throw new IllegalArgumentException("No process definition found for process " + processDefinitionKey);
184 }
185
186 return processInstance;
187 }
188
189
190
191
192
193
194 public Object advanceProcess(Object executionId) throws Exception
195 {
196 return advanceProcess(executionId, null, null);
197 }
198
199
200
201
202
203
204
205 @Override
206 public Object advanceProcess(Object executionId, Object signalName, Map variables) throws Exception
207 {
208 int waitTime = 0;
209 Execution execution = processEngine.getExecutionService().findExecutionById((String) executionId);
210 while (execution == null && waitTime < PROCESS_CREATION_WAIT)
211 {
212
213
214
215 Thread.sleep(PROCESS_CREATION_WAIT / 10);
216 waitTime += (PROCESS_CREATION_WAIT / 10);
217 execution = processEngine.getExecutionService().findExecutionById((String) executionId);
218 }
219 if (execution == null)
220 {
221 throw new IllegalArgumentException("No process execution found with id = " + executionId + " (it may have already terminated)");
222 }
223
224 String processId;
225 if (execution.getProcessInstance() != null)
226 {
227 processId = execution.getProcessInstance().getId();
228 }
229 else
230 {
231 processId = execution.getId();
232 }
233
234
235 if (variables != null && !variables.isEmpty())
236 {
237 processEngine.getExecutionService().setVariables((String) executionId, variables);
238 }
239
240
241 synchronized (this)
242 {
243 processEngine.getExecutionService().signalExecutionById((String) executionId, (String) signalName, variables);
244 }
245
246
247 ProcessInstance process = processEngine.getExecutionService().findProcessInstanceById(processId);
248 if (process == null)
249 {
250
251 process = new EndedProcess(processId);
252 }
253 return process;
254 }
255
256
257
258
259
260
261 @Override
262 public Object updateProcess(Object executionId, Map variables) throws Exception
263 {
264
265 String processId;
266 Execution execution = processEngine.getExecutionService().findExecutionById((String) executionId);
267 if (execution == null)
268 {
269 throw new IllegalArgumentException("No process execution found with id = " + executionId + " (it may have already terminated)");
270 }
271 if (execution.getProcessInstance() != null)
272 {
273 processId = execution.getProcessInstance().getId();
274 }
275 else
276 {
277 processId = execution.getId();
278 }
279
280
281 if (variables != null && !variables.isEmpty())
282 {
283 processEngine.getExecutionService().setVariables((String) executionId, variables);
284 }
285
286
287 ProcessInstance process = processEngine.getExecutionService().findProcessInstanceById(processId);
288 if (process == null)
289 {
290
291 process = new EndedProcess(processId);
292 }
293 return process;
294 }
295
296
297
298
299 @Override
300 public void abortProcess(Object processInstanceId) throws Exception
301 {
302 processEngine.getExecutionService().endProcessInstance((String) processInstanceId, Execution.STATE_ENDED);
303 }
304
305
306
307
308
309 @Override
310 public boolean isProcess(Object obj) throws Exception
311 {
312 return (obj instanceof ProcessInstance);
313 }
314
315 @Override
316 public Object getId(Object process) throws Exception
317 {
318 return ((ProcessInstance) process).getId();
319 }
320
321 @Override
322 public Object getState(Object process) throws Exception
323 {
324 return getState((ProcessInstance) process);
325 }
326
327 public static String getState(ProcessInstance processInstance) throws Exception
328 {
329 if (processInstance == null || processInstance.isEnded())
330 {
331 return ProcessInstance.STATE_ENDED;
332 }
333
334 Set activities = processInstance.findActiveActivityNames();
335 String state = null;
336
337 for (Object activityName : activities)
338 {
339 if (state == null)
340 {
341 state = (String) activityName;
342 }
343 else
344 {
345 state += " / " + activityName;
346 }
347 }
348 return state;
349 }
350
351 @Override
352 public boolean hasEnded(Object process) throws Exception
353 {
354 return process == null ? true : ((ProcessInstance) process).isEnded();
355 }
356
357
358
359
360
361
362 @Override
363 public Object lookupProcess(Object processId) throws Exception
364 {
365 return processEngine.getExecutionService().findProcessInstanceById((String) processId);
366 }
367
368
369
370
371
372 @Override
373 public void deployProcess(String processDefinitionFile) throws IOException
374 {
375 deployProcessFromStream(processDefinitionFile, IOUtils.getResourceAsStream(processDefinitionFile,
376 getClass()));
377 }
378
379 public void deployProcessFromStream(String resourceName, InputStream processDefinition)
380 throws IOException
381 {
382 processEngine.getRepositoryService().createDeployment()
383 .addResourceFromInputStream(resourceName, processDefinition)
384 .deploy();
385 }
386
387 @Override
388 public void undeployProcess(String resource) throws Exception
389 {
390
391 }
392
393 public void completeTask(Task task)
394 {
395 completeTask(task, null, null);
396 }
397
398 public void completeTask(Task task, String outcome, Map variables)
399 {
400 processEngine.getTaskService().completeTask(task.getId(), outcome, variables);
401 }
402
403
404
405
406
407 public ProcessEngine getProcessEngine()
408 {
409 return processEngine;
410 }
411
412 public void setProcessEngine(ProcessEngine processEngine)
413 {
414 this.processEngine = processEngine;
415 }
416
417 public String getConfigurationResource()
418 {
419 return configurationResource;
420 }
421
422 public void setConfigurationResource(String configurationResource)
423 {
424 this.configurationResource = configurationResource;
425 }
426
427 public Properties getProcessDefinitions()
428 {
429 return processDefinitions;
430 }
431
432 public void setProcessDefinitions(Properties processDefinitions)
433 {
434 this.processDefinitions = processDefinitions;
435 }
436
437 @Override
438 public void setName(String name)
439 {
440 this.name = name;
441 }
442
443 @Override
444 public String getName()
445 {
446 return name;
447 }
448 }