001: /*
002: * $Id: JmsServiceEngine.java,v 1.1 2003/08/17 05:12:38 ajzeneski Exp $
003: *
004: * Copyright (c) 2001, 2002 The Open For Business Project - www.ofbiz.org
005: *
006: * Permission is hereby granted, free of charge, to any person obtaining a
007: * copy of this software and associated documentation files (the "Software"),
008: * to deal in the Software without restriction, including without limitation
009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
010: * and/or sell copies of the Software, and to permit persons to whom the
011: * Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included
014: * in all copies or substantial portions of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023: */
024: package org.ofbiz.service.jms;
025:
026: import java.util.ArrayList;
027: import java.util.HashMap;
028: import java.util.Iterator;
029: import java.util.List;
030: import java.util.Map;
031:
032: import javax.jms.JMSException;
033: import javax.jms.MapMessage;
034: import javax.jms.Message;
035: import javax.jms.Queue;
036: import javax.jms.QueueConnection;
037: import javax.jms.QueueConnectionFactory;
038: import javax.jms.QueueSender;
039: import javax.jms.QueueSession;
040: import javax.jms.Session;
041: import javax.jms.Topic;
042: import javax.jms.TopicConnection;
043: import javax.jms.TopicConnectionFactory;
044: import javax.jms.TopicPublisher;
045: import javax.jms.TopicSession;
046: import javax.jms.XAQueueConnection;
047: import javax.jms.XAQueueConnectionFactory;
048: import javax.jms.XAQueueSession;
049: import javax.naming.InitialContext;
050: import javax.naming.NamingException;
051: import javax.transaction.xa.XAResource;
052:
053: import org.ofbiz.base.config.GenericConfigException;
054: import org.ofbiz.base.util.Debug;
055: import org.ofbiz.base.util.GeneralException;
056: import org.ofbiz.base.util.JNDIContextFactory;
057: import org.ofbiz.base.util.UtilXml;
058: import org.ofbiz.entity.serialize.XmlSerializer;
059: import org.ofbiz.entity.transaction.GenericTransactionException;
060: import org.ofbiz.entity.transaction.TransactionUtil;
061: import org.ofbiz.service.GenericRequester;
062: import org.ofbiz.service.GenericServiceException;
063: import org.ofbiz.service.ModelService;
064: import org.ofbiz.service.ServiceDispatcher;
065: import org.ofbiz.service.ServiceUtil;
066: import org.ofbiz.service.config.ServiceConfigUtil;
067: import org.ofbiz.service.engine.GenericEngine;
068: import org.w3c.dom.Element;
069:
070: /**
071: * AbstractJMSEngine
072: *
073: * @author <a href="mailto:jaz@ofbiz.org">Andy Zeneski</a>
074: * @version $Revision: 1.1 $
075: * @since 2.0
076: */
077: public class JmsServiceEngine implements GenericEngine {
078:
079: public static final String module = JmsServiceEngine.class
080: .getName();
081:
082: protected ServiceDispatcher dispatcher;
083:
084: public JmsServiceEngine(ServiceDispatcher dispatcher) {
085: this .dispatcher = dispatcher;
086: }
087:
088: protected Element getServiceElement(ModelService modelService)
089: throws GenericServiceException {
090: Element rootElement = null;
091:
092: try {
093: rootElement = ServiceConfigUtil.getXmlRootElement();
094: } catch (GenericConfigException e) {
095: throw new GenericServiceException(
096: "Error getting JMS Service element", e);
097: }
098: Element serviceElement = UtilXml.firstChildElement(rootElement,
099: "jms-service", "name", modelService.location);
100:
101: if (serviceElement == null) {
102: throw new GenericServiceException(
103: "Cannot find an JMS service definition for the name ["
104: + modelService.location
105: + "] in the serviceengine.xml file");
106: }
107: return serviceElement;
108: }
109:
110: protected Message makeMessage(Session session,
111: ModelService modelService, Map context)
112: throws GenericServiceException, JMSException {
113: List outParams = modelService.getParameterNames(
114: ModelService.OUT_PARAM, false);
115:
116: if (outParams != null && outParams.size() > 0)
117: throw new GenericServiceException(
118: "JMS service cannot have required OUT parameters; no parameters will be returned.");
119: String xmlContext = null;
120:
121: try {
122: if (Debug.verboseOn())
123: Debug.logVerbose("Serializing Context --> " + context,
124: module);
125: xmlContext = XmlSerializer.serialize(context);
126: } catch (Exception e) {
127: throw new GenericServiceException(
128: "Cannot serialize context.", e);
129: }
130: MapMessage message = session.createMapMessage();
131:
132: message.setString("serviceName", modelService.invoke);
133: message.setString("serviceContext", xmlContext);
134: return message;
135: }
136:
137: protected List serverList(Element serviceElement)
138: throws GenericServiceException {
139: String sendMode = serviceElement.getAttribute("send-mode");
140: List serverList = UtilXml.childElementList(serviceElement,
141: "server");
142:
143: if (sendMode.equals("none")) {
144: return new ArrayList();
145: } else if (sendMode.equals("all")) {
146: return serverList;
147: } else {
148: throw new GenericServiceException(
149: "Requested send mode not supported.");
150: }
151: }
152:
153: protected Map runTopic(ModelService modelService, Map context,
154: Element server) throws GenericServiceException {
155: String serverName = server.getAttribute("jndi-server-name");
156: String jndiName = server.getAttribute("jndi-name");
157: String topicName = server.getAttribute("topic-queue");
158: String userName = server.getAttribute("username");
159: String password = server.getAttribute("password");
160: String clientId = server.getAttribute("client-id");
161:
162: InitialContext jndi = null;
163: TopicConnectionFactory factory = null;
164: TopicConnection con = null;
165:
166: try {
167: jndi = JNDIContextFactory.getInitialContext(serverName);
168: factory = (TopicConnectionFactory) jndi.lookup(jndiName);
169: } catch (GeneralException ge) {
170: throw new GenericServiceException(
171: "Problems getting JNDI InitialContext.", ge
172: .getNested());
173: } catch (NamingException ne) {
174: JNDIContextFactory.clearInitialContext(serverName);
175: try {
176: jndi = JNDIContextFactory.getInitialContext(serverName);
177: factory = (TopicConnectionFactory) jndi
178: .lookup(jndiName);
179: } catch (GeneralException ge2) {
180: throw new GenericServiceException(
181: "Problems getting JNDI InitialContext.", ge2
182: .getNested());
183: } catch (NamingException ne2) {
184: throw new GenericServiceException(
185: "JNDI lookup problems.", ne);
186: }
187: }
188:
189: try {
190: con = factory.createTopicConnection(userName, password);
191:
192: if (clientId != null && clientId.length() > 1)
193: con.setClientID(clientId);
194: con.start();
195:
196: TopicSession session = con.createTopicSession(false,
197: Session.AUTO_ACKNOWLEDGE);
198: Topic topic = (Topic) jndi.lookup(topicName);
199: TopicPublisher publisher = session.createPublisher(topic);
200:
201: // create/send the message
202: Message message = makeMessage(session, modelService,
203: context);
204:
205: publisher.publish(message);
206: if (Debug.verboseOn())
207: Debug.logVerbose("Sent JMS Message to " + topicName,
208: module);
209:
210: // close the connections
211: publisher.close();
212: session.close();
213: con.close();
214: } catch (NamingException ne) {
215: throw new GenericServiceException(
216: "Problems with JNDI lookup.", ne);
217: } catch (JMSException je) {
218: throw new GenericServiceException("JMS Internal Error.", je);
219: }
220: return ServiceUtil.returnSuccess();
221:
222: }
223:
224: protected Map runQueue(ModelService modelService, Map context,
225: Element server) throws GenericServiceException {
226: String serverName = server.getAttribute("jndi-server-name");
227: String jndiName = server.getAttribute("jndi-name");
228: String queueName = server.getAttribute("topic-queue");
229: String userName = server.getAttribute("username");
230: String password = server.getAttribute("password");
231: String clientId = server.getAttribute("client-id");
232:
233: InitialContext jndi = null;
234: QueueConnectionFactory factory = null;
235: QueueConnection con = null;
236:
237: try {
238: jndi = JNDIContextFactory.getInitialContext(serverName);
239: factory = (QueueConnectionFactory) jndi.lookup(jndiName);
240: } catch (GeneralException ge) {
241: throw new GenericServiceException(
242: "Problems getting JNDI InitialContext.", ge
243: .getNested());
244: } catch (NamingException ne) {
245: JNDIContextFactory.clearInitialContext(serverName);
246: try {
247: jndi = JNDIContextFactory.getInitialContext(serverName);
248: factory = (QueueConnectionFactory) jndi
249: .lookup(jndiName);
250: } catch (GeneralException ge2) {
251: throw new GenericServiceException(
252: "Problems getting JNDI InitialContext.", ge2
253: .getNested());
254: } catch (NamingException ne2) {
255: throw new GenericServiceException(
256: "JNDI lookup problem.", ne2);
257: }
258: }
259:
260: try {
261: con = factory.createQueueConnection(userName, password);
262:
263: if (clientId != null && clientId.length() > 1)
264: con.setClientID(clientId);
265: con.start();
266:
267: QueueSession session = con.createQueueSession(false,
268: Session.AUTO_ACKNOWLEDGE);
269: Queue queue = (Queue) jndi.lookup(queueName);
270: QueueSender sender = session.createSender(queue);
271:
272: // create/send the message
273: Message message = makeMessage(session, modelService,
274: context);
275:
276: sender.send(message);
277: if (Debug.verboseOn())
278: Debug.logVerbose("Sent JMS Message to " + queueName,
279: module);
280:
281: // close the connections
282: sender.close();
283: session.close();
284: con.close();
285: } catch (NamingException ne) {
286: throw new GenericServiceException(
287: "Problems with JNDI lookup.", ne);
288: } catch (JMSException je) {
289: throw new GenericServiceException("JMS Internal Error.", je);
290: }
291: return ServiceUtil.returnSuccess();
292: }
293:
294: protected Map runXaQueue(ModelService modelService, Map context,
295: Element server) throws GenericServiceException {
296: String serverName = server.getAttribute("jndi-server-name");
297: String jndiName = server.getAttribute("jndi-name");
298: String queueName = server.getAttribute("topic-queue");
299: String userName = server.getAttribute("username");
300: String password = server.getAttribute("password");
301: String clientId = server.getAttribute("client-id");
302:
303: InitialContext jndi = null;
304: XAQueueConnectionFactory factory = null;
305: XAQueueConnection con = null;
306:
307: try {
308: jndi = JNDIContextFactory.getInitialContext(serverName);
309: factory = (XAQueueConnectionFactory) jndi.lookup(jndiName);
310: } catch (GeneralException ge) {
311: throw new GenericServiceException(
312: "Problems getting JNDI InitialContext.", ge
313: .getNested());
314: } catch (NamingException ne) {
315: JNDIContextFactory.clearInitialContext(serverName);
316: try {
317: jndi = JNDIContextFactory.getInitialContext(serverName);
318: factory = (XAQueueConnectionFactory) jndi
319: .lookup(jndiName);
320: } catch (GeneralException ge2) {
321: throw new GenericServiceException(
322: "Problems getting JNDI InitialContext.", ge2
323: .getNested());
324: } catch (NamingException ne2) {
325: throw new GenericServiceException(
326: "JNDI lookup problems.", ne2);
327: }
328: }
329:
330: try {
331: con = factory.createXAQueueConnection(userName, password);
332:
333: if (clientId != null && clientId.length() > 1)
334: con.setClientID(userName);
335: con.start();
336:
337: // enlist the XAResource
338: XAQueueSession session = con.createXAQueueSession();
339: XAResource resource = session.getXAResource();
340:
341: if (TransactionUtil.getStatus() == TransactionUtil.STATUS_ACTIVE)
342: TransactionUtil.enlistResource(resource);
343:
344: Queue queue = (Queue) jndi.lookup(queueName);
345: QueueSession qSession = session.getQueueSession();
346: QueueSender sender = qSession.createSender(queue);
347:
348: // create/send the message
349: Message message = makeMessage(session, modelService,
350: context);
351:
352: sender.send(message);
353:
354: if (TransactionUtil.getStatus() != TransactionUtil.STATUS_ACTIVE)
355: session.commit();
356:
357: Debug.logInfo("Message sent.", module);
358:
359: // close the connections
360: sender.close();
361: session.close();
362: con.close();
363: } catch (GenericTransactionException gte) {
364: throw new GenericServiceException(
365: "Problems enlisting resource w/ transaction manager.",
366: gte.getNested());
367: } catch (NamingException ne) {
368: throw new GenericServiceException(
369: "Problems with JNDI lookup.", ne);
370: } catch (JMSException je) {
371: throw new GenericServiceException("JMS Internal Error.", je);
372: }
373: return ServiceUtil.returnSuccess();
374: }
375:
376: protected Map run(ModelService modelService, Map context)
377: throws GenericServiceException {
378: Element serviceElement = getServiceElement(modelService);
379: List serverList = serverList(serviceElement);
380:
381: Map result = new HashMap();
382: Iterator i = serverList.iterator();
383:
384: while (i.hasNext()) {
385: Element server = (Element) i.next();
386: String serverType = server.getAttribute("type");
387:
388: if (serverType.equals("topic"))
389: result.putAll(runTopic(modelService, context, server));
390: else if (serverType.equals("queue"))
391: result.putAll(runQueue(modelService, context, server));
392: else
393: throw new GenericServiceException(
394: "Illegal server messaging type.");
395: }
396: return result;
397: }
398:
399: /**
400: * @see org.ofbiz.service.engine.GenericEngine#runSync(java.lang.String, org.ofbiz.service.ModelService, java.util.Map)
401: */
402: public Map runSync(String localName, ModelService modelService,
403: Map context) throws GenericServiceException {
404: return run(modelService, context);
405: }
406:
407: /**
408: * @see org.ofbiz.service.engine.GenericEngine#runSyncIgnore(java.lang.String, org.ofbiz.service.ModelService, java.util.Map)
409: */
410: public void runSyncIgnore(String localName,
411: ModelService modelService, Map context)
412: throws GenericServiceException {
413: run(modelService, context);
414: }
415:
416: /**
417: * @see org.ofbiz.service.engine.GenericEngine#runAsync(java.lang.String, org.ofbiz.service.ModelService, java.util.Map, org.ofbiz.service.GenericRequester, boolean)
418: */
419: public void runAsync(String localName, ModelService modelService,
420: Map context, GenericRequester requester, boolean persist)
421: throws GenericServiceException {
422: Map result = run(modelService, context);
423:
424: requester.receiveResult(result);
425: }
426:
427: /**
428: * @see org.ofbiz.service.engine.GenericEngine#runAsync(java.lang.String, org.ofbiz.service.ModelService, java.util.Map, boolean)
429: */
430: public void runAsync(String localName, ModelService modelService,
431: Map context, boolean persist)
432: throws GenericServiceException {
433: run(modelService, context);
434: }
435:
436: }
|