KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ofbiz > webapp > event > ServiceMultiEventHandler


1 /*
2  * $Id: ServiceMultiEventHandler.java 6583 2006-01-25 20:24:44Z jonesde $
3  *
4  * Copyright (c) 2003-2005 The Open For Business Project - www.ofbiz.org
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
21  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  */

25 package org.ofbiz.webapp.event;
26
27 import java.util.Arrays JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.List JavaDoc;
31 import java.util.Locale JavaDoc;
32 import java.util.Map JavaDoc;
33
34 import javax.servlet.ServletContext JavaDoc;
35 import javax.servlet.http.HttpServletRequest JavaDoc;
36 import javax.servlet.http.HttpServletResponse JavaDoc;
37 import javax.servlet.http.HttpSession JavaDoc;
38
39 import javolution.util.FastList;
40 import javolution.util.FastMap;
41
42 import org.ofbiz.base.util.Debug;
43 import org.ofbiz.base.util.UtilHttp;
44 import org.ofbiz.base.util.UtilProperties;
45 import org.ofbiz.base.util.UtilValidate;
46 import org.ofbiz.entity.GenericValue;
47 import org.ofbiz.entity.transaction.GenericTransactionException;
48 import org.ofbiz.entity.transaction.TransactionUtil;
49 import org.ofbiz.service.DispatchContext;
50 import org.ofbiz.service.GenericServiceException;
51 import org.ofbiz.service.LocalDispatcher;
52 import org.ofbiz.service.ModelParam;
53 import org.ofbiz.service.ModelService;
54 import org.ofbiz.service.ServiceAuthException;
55 import org.ofbiz.service.ServiceUtil;
56 import org.ofbiz.service.ServiceValidationException;
57 import org.ofbiz.webapp.control.RequestHandler;
58 import org.ofbiz.webapp.control.RequestManager;
59
60 /**
61  * ServiceMultiEventHandler - Event handler for running a service multiple times; for bulk forms
62  *
63  * @author <a HREF="mailto:jaz@ofbiz.org">Andy Zeneski</a>
64  * @version $Rev: 6583 $
65  * @since 2.2
66  */

67 public class ServiceMultiEventHandler implements EventHandler {
68
69     public static final String JavaDoc module = ServiceMultiEventHandler.class.getName();
70
71     public static final String JavaDoc SYNC = "sync";
72     public static final String JavaDoc ASYNC = "async";
73     private RequestManager requestManager;
74
75     /**
76      * @see org.ofbiz.webapp.event.EventHandler#init(javax.servlet.ServletContext)
77      */

78     public void init(ServletContext JavaDoc context) throws EventHandlerException {
79
80         // Provide a means to check the controller for event tag attributes at execution time
81
this.requestManager = new RequestManager(context);
82     }
83
84     /**
85      * @see org.ofbiz.webapp.event.EventHandler#invoke(java.lang.String, java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
86      */

87     public String JavaDoc invoke(String JavaDoc eventPath, String JavaDoc eventMethod, HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response) throws EventHandlerException {
88         // TODO: consider changing this to use the new UtilHttp.parseMultiFormData method
89

90         // make sure we have a valid reference to the Service Engine
91
LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
92         if (dispatcher == null) {
93             throw new EventHandlerException("The local service dispatcher is null");
94         }
95         DispatchContext dctx = dispatcher.getDispatchContext();
96         if (dctx == null) {
97             throw new EventHandlerException("Dispatch context cannot be found");
98         }
99
100         // get the details for the service(s) to call
101
String JavaDoc mode = SYNC;
102         String JavaDoc serviceName = null;
103
104         if (eventPath == null || eventPath.length() == 0) {
105             mode = SYNC;
106         } else {
107             mode = eventPath;
108         }
109
110         // we only support SYNC mode in this handler
111
if (mode != SYNC) {
112             throw new EventHandlerException("Async mode is not supported");
113         }
114
115         // nake sure we have a defined service to call
116
serviceName = eventMethod;
117         if (serviceName == null) {
118             throw new EventHandlerException("Service name (eventMethod) cannot be null");
119         }
120         if (Debug.verboseOn()) Debug.logVerbose("[Set mode/service]: " + mode + "/" + serviceName, module);
121
122         // some needed info for when running the service
123
Locale JavaDoc locale = UtilHttp.getLocale(request);
124         HttpSession JavaDoc session = request.getSession();
125         GenericValue userLogin = (GenericValue) session.getAttribute("userLogin");
126
127         // get the service model to generate context(s)
128
ModelService modelService = null;
129
130         try {
131             modelService = dctx.getModelService(serviceName);
132         } catch (GenericServiceException e) {
133             throw new EventHandlerException("Problems getting the service model", e);
134         }
135
136         if (modelService == null) {
137             throw new EventHandlerException("Problems getting the service model");
138         }
139
140         if (Debug.verboseOn()) Debug.logVerbose("[Processing]: SERVICE Event", module);
141         if (Debug.verboseOn()) Debug.logVerbose("[Using delegator]: " + dispatcher.getDelegator().getDelegatorName(), module);
142
143         // check if we are using per row submit
144
boolean useRowSubmit = request.getParameter("_useRowSubmit") == null ? false :
145                 "Y".equalsIgnoreCase(request.getParameter("_useRowSubmit"));
146
147         // check if we are to also look in a global scope (no delimiter)
148
boolean checkGlobalScope = request.getParameter("_checkGlobalScope") == null ? true :
149                 !"N".equalsIgnoreCase(request.getParameter("_checkGlobalScope"));
150
151         // get the number of rows
152
String JavaDoc rowCountField = request.getParameter("_rowCount");
153         if (rowCountField == null) {
154             throw new EventHandlerException("Required field _rowCount is missing");
155         }
156
157         int rowCount = 0; // parsed int value
158
try {
159             rowCount = Integer.parseInt(rowCountField);
160         } catch (NumberFormatException JavaDoc e) {
161             throw new EventHandlerException("Invalid value for _rowCount");
162         }
163         if (rowCount < 1) {
164             throw new EventHandlerException("No rows to process");
165         }
166
167         // some default message settings
168
String JavaDoc errorPrefixStr = UtilProperties.getMessage("DefaultMessages", "service.error.prefix", locale);
169         String JavaDoc errorSuffixStr = UtilProperties.getMessage("DefaultMessages", "service.error.suffix", locale);
170         String JavaDoc messagePrefixStr = UtilProperties.getMessage("DefaultMessages", "service.message.prefix", locale);
171         String JavaDoc messageSuffixStr = UtilProperties.getMessage("DefaultMessages", "service.message.suffix", locale);
172
173         // prepare the error message list
174
List JavaDoc errorMessages = FastList.newInstance();
175
176         // Check the global-transaction attribute of the event from the controller to see if the
177
// event should be wrapped in a transaction
178
String JavaDoc requestUri = RequestHandler.getRequestUri(request.getPathInfo());
179         boolean eventGlobalTransaction = requestManager.getEventGlobalTransaction(requestUri);
180
181         // big try/finally to make sure commit or rollback are run
182
boolean beganTrans = false;
183         String JavaDoc returnString = null;
184         try {
185
186             if (eventGlobalTransaction) {
187                 // start the global transaction
188
try {
189                     beganTrans = TransactionUtil.begin(modelService.transactionTimeout * rowCount);
190                 } catch (GenericTransactionException e) {
191                     throw new EventHandlerException("Problem starting multi-service global transaction", e);
192                 }
193             }
194
195             // now loop throw the rows and prepare/invoke the service for each
196
for (int i = 0; i < rowCount; i++) {
197                 String JavaDoc curSuffix = UtilHttp.MULTI_ROW_DELIMITER + i;
198                 boolean rowSelected = request.getParameter(UtilHttp.ROW_SUBMIT_PREFIX + i) == null ? false :
199                         "Y".equalsIgnoreCase(request.getParameter(UtilHttp.ROW_SUBMIT_PREFIX + i));
200
201                 // make sure we are to process this row
202
if (useRowSubmit && !rowSelected) {
203                     continue;
204                 }
205
206                 // build the context
207
Map JavaDoc serviceContext = FastMap.newInstance();
208                 List JavaDoc modelParmInList = modelService.getInModelParamList();
209                 Iterator JavaDoc modelParmInIter = modelParmInList.iterator();
210                 while (modelParmInIter.hasNext()) {
211                     ModelParam modelParam = (ModelParam) modelParmInIter.next();
212                     String JavaDoc paramName = (String JavaDoc) modelParam.name;
213                     
214                     // Debug.logInfo("In ServiceMultiEventHandler processing input parameter [" + modelParam.name + (modelParam.optional?"(optional):":"(required):") + modelParam.mode + "] for service [" + serviceName + "]", module);
215

216                     // don't include userLogin, that's taken care of below
217
if ("userLogin".equals(paramName)) continue;
218                     // don't include locale, that is also taken care of below
219
if ("locale".equals(paramName)) continue;
220
221                     Object JavaDoc value = null;
222                     if (modelParam.stringMapPrefix != null && modelParam.stringMapPrefix.length() > 0) {
223                         Map JavaDoc paramMap = UtilHttp.makeParamMapWithPrefix(request, modelParam.stringMapPrefix, curSuffix);
224                         value = paramMap;
225                     } else if (modelParam.stringListSuffix != null && modelParam.stringListSuffix.length() > 0) {
226                         List JavaDoc paramList = UtilHttp.makeParamListWithSuffix(request, modelParam.stringListSuffix, null);
227                         value = paramList;
228                     } else {
229                         // first check for request parameters
230
String JavaDoc[] paramArr = request.getParameterValues(paramName + curSuffix);
231                         if (paramArr != null) {
232                             if (paramArr.length > 1) {
233                                 value = Arrays.asList(paramArr);
234                             } else {
235                                 value = paramArr[0];
236                             }
237                         }
238
239                         // if the parameter wasn't passed and no other value found, don't pass on the null
240
if (value == null) {
241                             value = request.getAttribute(paramName + curSuffix);
242                         }
243                         if (value == null) {
244                             value = session.getAttribute(paramName + curSuffix);
245                         }
246
247                         // now check global scope
248
if (value == null) {
249                             if (checkGlobalScope) {
250                                 String JavaDoc[] gParamArr = request.getParameterValues(paramName);
251                                 if (gParamArr != null) {
252                                     if (gParamArr.length > 1) {
253                                         value = Arrays.asList(gParamArr);
254                                     } else {
255                                         value = gParamArr[0];
256                                     }
257                                 }
258                                 if (value == null) {
259                                     value = request.getAttribute(paramName);
260                                 }
261                                 if (value == null) {
262                                     value = session.getAttribute(paramName);
263                                 }
264                             }
265                         }
266
267                         if (value == null) {
268                             // still null, give up for this one
269
continue;
270                         }
271
272                         if (value instanceof String JavaDoc && ((String JavaDoc) value).length() == 0) {
273                             // interpreting empty fields as null values for each in back end handling...
274
value = null;
275                         }
276                     }
277                     // set even if null so that values will get nulled in the db later on
278
serviceContext.put(paramName, value);
279
280                     // Debug.logInfo("In ServiceMultiEventHandler got value [" + value + "] for input parameter [" + paramName + "] for service [" + serviceName + "]", module);
281
}
282
283                 // get only the parameters for this service - converted to proper type
284
serviceContext = modelService.makeValid(serviceContext, ModelService.IN_PARAM, true, null, locale);
285
286                 // include the UserLogin value object
287
if (userLogin != null) {
288                     serviceContext.put("userLogin", userLogin);
289                 }
290
291                 // include the Locale object
292
if (locale != null) {
293                     serviceContext.put("locale", locale);
294                 }
295
296                 // Debug.logInfo("ready to call " + serviceName + " with context " + serviceContext, module);
297

298                 // invoke the service
299
Map JavaDoc result = null;
300                 try {
301                     result = dispatcher.runSync(serviceName, serviceContext);
302                 } catch (ServiceAuthException e) {
303                     // not logging since the service engine already did
304
errorMessages.add(messagePrefixStr + "Service invocation error on row (" + i +"): " + e.getNonNestedMessage());
305                 } catch (ServiceValidationException e) {
306                     // not logging since the service engine already did
307
request.setAttribute("serviceValidationException", e);
308                     List JavaDoc errors = e.getMessageList();
309                     if (errors != null) {
310                         Iterator JavaDoc erri = errors.iterator();
311                         while (erri.hasNext()) {
312                             errorMessages.add("Service invocation error on row (" + i + "): " + erri.next());
313                         }
314                     } else {
315                         errorMessages.add(messagePrefixStr + "Service invocation error on row (" + i +"): " + e.getNonNestedMessage());
316                     }
317                 } catch (GenericServiceException e) {
318                     Debug.logError(e, "Service invocation error", module);
319                     errorMessages.add(messagePrefixStr + "Service invocation error on row (" + i +"): " + e.getNested() + messageSuffixStr);
320                 }
321
322                 // check for an error message
323
String JavaDoc errorMessage = ServiceUtil.makeErrorMessage(result, messagePrefixStr, messageSuffixStr, "", "");
324                 if (UtilValidate.isNotEmpty(errorMessage)) {
325                     errorMessages.add(errorMessage);
326                 }
327                 
328                 // set the results in the request
329
if ((result != null) && (result.entrySet() != null)) {
330                     Iterator JavaDoc rmei = result.entrySet().iterator();
331                     while (rmei.hasNext()) {
332                         Map.Entry JavaDoc rme = (Map.Entry JavaDoc) rmei.next();
333                         String JavaDoc resultKey = (String JavaDoc) rme.getKey();
334                         Object JavaDoc resultValue = rme.getValue();
335
336                         if (resultKey != null && !ModelService.RESPONSE_MESSAGE.equals(resultKey) && !ModelService.ERROR_MESSAGE.equals(resultKey) &&
337                                 !ModelService.ERROR_MESSAGE_LIST.equals(resultKey) && !ModelService.ERROR_MESSAGE_MAP.equals(resultKey) &&
338                                 !ModelService.SUCCESS_MESSAGE.equals(resultKey) && !ModelService.SUCCESS_MESSAGE_LIST.equals(resultKey)) {
339                             request.setAttribute(resultKey, resultValue);
340                         }
341                     }
342                 }
343             }
344         } finally {
345             if (errorMessages.size() > 0) {
346                 if (eventGlobalTransaction) {
347                     // rollback the global transaction
348
try {
349                         TransactionUtil.rollback(beganTrans, "Error in multi-service event handling: " + errorMessages.toString(), null);
350                     } catch (GenericTransactionException e) {
351                         Debug.logError(e, "Could not rollback multi-service global transaction", module);
352                     }
353                 }
354                 errorMessages.add(0, errorPrefixStr);
355                 errorMessages.add(errorSuffixStr);
356                 StringBuffer JavaDoc errorBuf = new StringBuffer JavaDoc();
357                 Iterator JavaDoc ei = errorMessages.iterator();
358                 while (ei.hasNext()) {
359                     String JavaDoc em = (String JavaDoc) ei.next();
360                     errorBuf.append(em + "\n");
361                 }
362                 request.setAttribute("_ERROR_MESSAGE_", errorBuf.toString());
363                 returnString = "error";
364             } else {
365                 if (eventGlobalTransaction) {
366                     // commit the global transaction
367
try {
368                         TransactionUtil.commit(beganTrans);
369                     } catch (GenericTransactionException e) {
370                         Debug.logError(e, "Could not commit multi-service global transaction", module);
371                         throw new EventHandlerException("Commit multi-service global transaction failed");
372                     }
373                 }
374                 returnString = "success";
375             }
376         }
377         
378         return returnString;
379     }
380 }
381
Popular Tags