View Javadoc

1   /*
2    * $Id: Dispatcher.java,v 1.1 2004/12/15 14:18:10 patforna Exp $
3    *
4    * Copyright (c) 2004 Patric Fornasier, Pawel Kowalski
5    * Berne University of Applied Sciences
6    * School of Engineering and Information Technology
7    * All rights reserved.
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          // get BPELProcess and ProcessContext for incoming message
69          BPELProcess process = getBPELProcess(message);
70          ProcessContext ctx = getProcessContext(message);
71  
72          // create instance from BPELProcess and ProcessContext
73          instance = new ProcessInstance(process, ctx);
74  
75          // create process controller
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          // get BPEL process and process context from process instance
100         ProcessContext ctx = instance.getContext();
101         BPELProcess process = instance.getProcess();
102 
103         // check if a context was found or created
104         if (ctx == null) {
105             throw new DispatcherException("No context found");
106         }
107 
108         // check if a process was found or created
109         if (process == null) {
110             throw new DispatcherException("No process found");
111         }
112 
113         // start processing
114         start();
115 
116         // if we have a synchronous process, wait until result is available
117         if (process.isSynchronous()) {
118             synchronized (ctx) {
119                 try {
120                     // wait until the process has finished and get the result
121                     ctx.wait();
122                     result = ctx.getResult();
123                 } catch (InterruptedException e) {
124                     throw new DispatcherException("Dispatcher interrupted", e);
125                 }
126             }
127         } else {
128             // TODO do we need to give something back here?
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          * TODO Correlation stuff for finding a running process context. Right
158          * now this isn't supported, so we create a new instance each time.
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 }