View Javadoc

1   /*
2    * $Id: MuleSendActivity.java 20121 2010-11-08 17:33:48Z tcarlson $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.module.jbpm;
12  
13  import org.mule.MessageExchangePattern;
14  import org.mule.api.MuleMessage;
15  import org.mule.api.config.MuleProperties;
16  import org.mule.module.bpm.MessageService;
17  import org.mule.module.bpm.Process;
18  import org.mule.util.ClassUtils;
19  
20  import java.util.HashMap;
21  import java.util.Map;
22  import java.util.Map.Entry;
23  
24  import org.jbpm.api.JbpmException;
25  import org.jbpm.api.activity.ActivityExecution;
26  import org.jbpm.api.listener.EventListener;
27  import org.jbpm.api.listener.EventListenerExecution;
28  import org.jbpm.api.model.OpenExecution;
29  import org.jbpm.internal.log.Log;
30  import org.jbpm.jpdl.internal.activity.JpdlActivity;
31  import org.jbpm.pvm.internal.env.EnvironmentImpl;
32  import org.jbpm.pvm.internal.model.ExecutionImpl;
33  import org.jbpm.pvm.internal.script.ScriptManager;
34  
35  public class MuleSendActivity extends JpdlActivity implements EventListener
36  {
37      /**
38       * Mule endpoint to send a message to.  This may be a URI or logical name (for a global endpoint).
39       */
40      private String endpoint;
41  
42      /**
43       * Exchange pattern (REQUEST-RESPONSE, ONE-WAY, etc.).  Default is REQUEST-RESPONSE.
44       */
45      private MessageExchangePattern mep = MessageExchangePattern.REQUEST_RESPONSE;
46      
47      /** 
48       * Expected response type in the case of a synchronous call; if the response payload is not assignable to this class, an exception will be thrown.
49       */
50      private Class responsePayloadClass;
51  
52      /**
53       * Variable into which the synchronous response will be stored.  If null, the response will not be stored at all.
54       */
55      private String responseVariableName;
56      
57      /**
58       * payloadSource may be a literal value or it may be an expression which references process variables.
59       */
60      private String payloadExpression;
61  
62      /**
63       * The actual payload (as an object) will be stored here.
64       */
65      private Object payloadObject;
66      
67      private static final Log log = Log.getLog(MuleSendActivity.class.getName());
68  
69      public void execute(ActivityExecution execution) throws Exception
70      {
71          perform(execution);
72          ((ExecutionImpl) execution).historyAutomatic();
73      }
74  
75      public void notify(EventListenerExecution execution) throws Exception
76      {
77          perform(execution);
78      }
79  
80      public void perform(OpenExecution execution) throws Exception
81      {
82          MessageService mule = EnvironmentImpl.getCurrent().get(MuleMessageService.class);
83          if (mule == null)
84          {
85              throw new JbpmException("The Mule MessageService is not available from the ProcessEngine, you may need to add it to your jbpm.cfg.xml file");
86          }
87  
88          if (payloadExpression == null)
89          {
90              payloadObject = execution.getVariable(Process.PROCESS_VARIABLE_DATA);
91              if (payloadObject == null)
92              {
93                  payloadObject = execution.getVariable(Process.PROCESS_VARIABLE_INCOMING);
94              }
95          }
96          else
97          {
98              // The payloadSource may be specified using an expression (e.g.,
99              // #{myObject.myStuff.myField} would first retrieve the process
100             // variable "myObject" and then call .getMyStuff().getMyField()
101             payloadObject = ScriptManager.getScriptManager().evaluateExpression(payloadExpression, null);
102         }
103         if (payloadObject == null)
104         {
105             throw new IllegalArgumentException("Payload for message is null.  Payload source is \""
106                                                + payloadExpression + "\"");
107         }
108 
109         Map props = new HashMap();
110 
111         props.put(Process.PROPERTY_PROCESS_TYPE, ((ExecutionImpl) execution).getProcessDefinition().getName());
112         props.put(Process.PROPERTY_PROCESS_ID, execution.getId());
113         String state = Jbpm.getState(execution.getProcessInstance());
114         props.put("MULE_BPM_PROCESS_STATE", state);
115         log.debug("process state: " + state);        
116 
117         // Set process vars as properties on outgoing Mule messages.
118         for (Entry<String, ?> var : execution.getVariables().entrySet())
119         {
120             if (!var.getKey().startsWith(MuleProperties.PROPERTY_PREFIX))
121             {
122                 log.debug("process var: " + var.getKey() + " = " + var.getValue());
123                 props.put(var.getKey(), var.getValue());
124             }
125         }
126 
127         // Just in case the endpoint itself is an expression
128         endpoint = (String) ScriptManager.getScriptManager().evaluateExpression(endpoint, null);
129         MuleMessage response = mule.generateMessage(endpoint, payloadObject, props, mep);
130 
131         if (mep.hasResponse() && response != null)
132         {
133             Object responsePayload = response.getPayload();
134     
135             // Validate expected response type
136             if (responsePayloadClass != null)
137             {
138                 log.debug("Validating response type = " + responsePayload.getClass() + ", expected = " + responsePayloadClass);
139                 if (!responsePayloadClass.isAssignableFrom(responsePayload.getClass()))
140                 {
141                     throw new JbpmException("Response message is of type " + responsePayload.getClass() + " but expected type is " + responsePayloadClass);
142                 }
143             }
144             
145             if (responseVariableName != null)
146             {
147                 if (responsePayload != null)
148                 {
149                     execution.setVariable(responseVariableName, responsePayload);
150                 }
151                 else
152                 {
153                     log.info("Synchronous message was sent to endpoint " + endpoint + ", but no response was returned.");
154                 }
155             }
156         }
157     }
158     
159     public void setEndpoint(String endpoint)
160     {
161         this.endpoint = endpoint;
162     }
163 
164     public void setMessageExchangePattern(String mepString)
165     {
166         if (mepString != null)
167         {
168             this.mep = MessageExchangePattern.fromString(mepString);
169         }
170     }
171 
172     public String getPayloadExpression()
173     {
174         return payloadExpression;
175     }
176 
177     public void setPayloadExpression(String payloadExpression)
178     {
179         this.payloadExpression = payloadExpression;
180     }
181 
182     public String getResponseVariableName()
183     {
184         return responseVariableName;
185     }
186 
187     public void setResponseVariableName(String responseVariableName)
188     {
189         this.responseVariableName = responseVariableName;
190     }
191 
192     public void setResponsePayloadClass(String className)
193     {
194         if (className != null)
195         {
196             try
197             {
198                 responsePayloadClass = ClassUtils.loadClass(className, this.getClass());
199             }
200             catch (ClassNotFoundException e)
201             {
202                 log.error("Expected message type not valid: " + e.getMessage());
203             }
204         }
205     }
206 
207     public Class getResponsePayloadClass()
208     {
209         return responsePayloadClass;
210     }
211 }