1
2
3
4
5
6
7
8
9 package bexee.core;
10
11 import org.apache.commons.logging.Log;
12 import org.apache.commons.logging.LogFactory;
13
14 import bexee.dao.BPELProcessDAO;
15 import bexee.dao.DAOException;
16 import bexee.dao.DAOFactory;
17 import bexee.model.process.BPELProcess;
18
19 /***
20 * This class is used to lookup or create a <code>ProcessInstance</code> given
21 * an inbound <code>BexeeMessage</code> and dispatch the message to the
22 * {@link bexee.core.ProcessController}either synchronously or asynchronoulsy.
23 * <p>
24 * To do this, create the object and then use its {@link #dispatch()}method.
25 * <p>
26 * When the <code>Dispatcher</code> kicks off the
27 * <code>ProcessController</code> it will know, whether a synchronous or
28 * asynchronous BPEL process is to be started. Depending on that it will either
29 * return right away after starting the process for an asynchronous BPEL process
30 * or it will wait until the result is available for a synchronous BPEL process.
31 * <p>
32 * Either way the <code>ProcessController</code>'s
33 * <code>processMessage()</code> method is started in a new Thread, but in
34 * case of a synchronous BPEL process the <code>Dispatcher</code> will wait
35 * until the result is available. This happens by obtaining a lock on the
36 * <code>ProcessContext</code>, which will notify the <code>Dispatcher</code>
37 * when the result is available.
38 *
39 * @version $Revision: 1.1 $, $Date: 2004/12/15 14:18:10 $
40 * @author Patric Fornasier
41 * @author Pawel Kowalski
42 */
43 public class Dispatcher extends Thread {
44
45 /***
46 * Result when processing an asynchronous result. This might change in
47 * future versions.
48 */
49 public static final String ASYNC_RESULT = "Processing request...";
50
51 protected ProcessController controller;
52
53 protected ProcessInstance instance;
54
55 protected BexeeMessage message;
56
57 private static Log log = LogFactory.getLog(Dispatcher.class);
58
59 /***
60 * Creates a new <code>Dispatcher</code> object.
61 *
62 * @param message
63 * the incoming message
64 */
65 public Dispatcher(BexeeMessage message) {
66 this.message = message;
67
68
69 BPELProcess process = getBPELProcess(message);
70 ProcessContext ctx = getProcessContext(message);
71
72
73 instance = new ProcessInstance(process, ctx);
74
75
76 controller = ProcessControllerFactory.createProcessController();
77 }
78
79 /***
80 * Calls the {@link ProcessController}s
81 * {@link ProcessController#processMessage(ProcessInstance, BexeeMessage)}
82 * method either synchronously or asynchronously.
83 * <p>
84 * Note that this method may take minutes or hours for long-running
85 * synchronous processes.
86 *
87 * @return the result
88 * @throws DispatcherException
89 * If something went wrong dispatching the message. This can
90 * happen for example if the <code>BPELProcess</code> or the
91 * <code>ProcessContext</code> can't be found or created or if
92 * something went wrong processing the message in the
93 * <code>ProcessController</code>.
94 */
95 public Object dispatch() throws DispatcherException {
96
97 Object result = null;
98
99
100 ProcessContext ctx = instance.getContext();
101 BPELProcess process = instance.getProcess();
102
103
104 if (ctx == null) {
105 throw new DispatcherException("No context found");
106 }
107
108
109 if (process == null) {
110 throw new DispatcherException("No process found");
111 }
112
113
114 start();
115
116
117 if (process.isSynchronous()) {
118 synchronized (ctx) {
119 try {
120
121 ctx.wait();
122 result = ctx.getResult();
123 } catch (InterruptedException e) {
124 throw new DispatcherException("Dispatcher interrupted", e);
125 }
126 }
127 } else {
128
129 result = ASYNC_RESULT;
130 }
131
132 return result;
133 }
134
135 /***
136 * Do not use this method directly. Use {@link #dispatch()}instead.
137 */
138 public void run() {
139 controller.processMessage(instance, message);
140 }
141
142 /***
143 * Gets the <code>ProcessContext</code> belonging to the incoming message.
144 *
145 * @param message
146 * the incoming message
147 * @return a new <code>ProcessContext</code> if there is currently no
148 * process running or the <code>ProcessContext</code> instance
149 * belonging to the incoming message if there is a process running
150 * already.
151 */
152 protected ProcessContext getProcessContext(BexeeMessage message) {
153
154 ProcessContext ctx = null;
155
156
157
158
159
160 ctx = new ProcessContext();
161
162 return ctx;
163 }
164
165 /***
166 * Gets the <code>BPELProcess</code> belonging to the incoming message.
167 *
168 * @param message
169 * the incoming message
170 * @return the <code>BPELProcess</code> that will be identified by the
171 * incoming message or null if it can't be found.
172 */
173 protected BPELProcess getBPELProcess(BexeeMessage message) {
174
175 BPELProcess process = null;
176 String name = message.getService();
177
178 DAOFactory factory = DAOFactory.getInstance();
179 BPELProcessDAO bpelDAO = factory.createBPELProcessDAO();
180
181 try {
182 process = bpelDAO.find(name);
183 } catch (DAOException e) {
184 log.info("Error trying to find process", e);
185 }
186
187 return process;
188 }
189 }