001: /*
002: * $Id: AbstractJavaComponent.java 11414 2008-03-18 03:16:19Z dfeist $
003: * --------------------------------------------------------------------------------------
004: * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com
005: *
006: * The software in this package is published under the terms of the CPAL v1.0
007: * license, a copy of which has been included with this distribution in the
008: * LICENSE.txt file.
009: */
010:
011: package org.mule.component;
012:
013: import org.mule.DefaultMuleMessage;
014: import org.mule.OptimizedRequestContext;
015: import org.mule.RequestContext;
016: import org.mule.api.ExceptionPayload;
017: import org.mule.api.MessagingException;
018: import org.mule.api.MuleEvent;
019: import org.mule.api.MuleException;
020: import org.mule.api.MuleMessage;
021: import org.mule.api.component.JavaComponent;
022: import org.mule.api.component.LifecycleAdapter;
023: import org.mule.api.component.LifecycleAdapterFactory;
024: import org.mule.api.config.MuleProperties;
025: import org.mule.api.endpoint.InboundEndpoint;
026: import org.mule.api.lifecycle.InitialisationException;
027: import org.mule.api.model.EntryPointResolver;
028: import org.mule.api.model.EntryPointResolverSet;
029: import org.mule.api.object.ObjectFactory;
030: import org.mule.api.routing.NestedRouterCollection;
031: import org.mule.api.transport.ReplyToHandler;
032: import org.mule.config.i18n.CoreMessages;
033: import org.mule.message.DefaultExceptionPayload;
034: import org.mule.model.resolvers.DefaultEntryPointResolverSet;
035: import org.mule.routing.nested.DefaultNestedRouterCollection;
036: import org.mule.transport.NullPayload;
037:
038: import java.util.Collection;
039: import java.util.Iterator;
040:
041: /**
042: * Abstract implementation of JavaComponent adds JavaComponent specific's:
043: * {@link EntryPointResolverSet}, {@link NestedRouterCollection} and
044: * {@link ObjectFactory}. Provides default implementations of doOnCall and doOnEvent
045: * and defines abstract template methods provided for obtaining and returning the
046: * component object instance.
047: */
048: public abstract class AbstractJavaComponent extends AbstractComponent
049: implements JavaComponent {
050:
051: protected EntryPointResolverSet entryPointResolverSet;
052:
053: protected NestedRouterCollection nestedRouter = new DefaultNestedRouterCollection();
054:
055: protected ObjectFactory objectFactory;
056:
057: protected LifecycleAdapterFactory lifecycleAdapterFactory;
058:
059: public AbstractJavaComponent() {
060: // For Spring only
061: }
062:
063: public AbstractJavaComponent(ObjectFactory objectFactory) {
064: this (objectFactory, null, null);
065: }
066:
067: public AbstractJavaComponent(ObjectFactory objectFactory,
068: EntryPointResolverSet entryPointResolverSet,
069: NestedRouterCollection nestedRouterCollection) {
070: this .objectFactory = objectFactory;
071: this .entryPointResolverSet = entryPointResolverSet;
072: if (nestedRouterCollection != null) {
073: this .nestedRouter = nestedRouterCollection;
074: }
075: }
076:
077: protected MuleMessage doOnCall(MuleEvent event) {
078: MuleMessage returnMessage = null;
079: try {
080: InboundEndpoint endpoint = (InboundEndpoint) event
081: .getEndpoint();
082: event = OptimizedRequestContext.unsafeSetEvent(event);
083: Object replyTo = event.getMessage().getReplyTo();
084: ReplyToHandler replyToHandler = getReplyToHandler(event
085: .getMessage(), endpoint);
086:
087: // TODO Move stats up into AbstractComponent once routing has been moved
088: // to service.
089:
090: // stats
091: long startTime = 0;
092: if (statistics.isEnabled()) {
093: startTime = System.currentTimeMillis();
094: }
095:
096: returnMessage = invokeComponentInstance(event);
097:
098: // stats
099: if (statistics.isEnabled()) {
100: statistics.addExecutionTime(System.currentTimeMillis()
101: - startTime);
102: }
103:
104: // TODO MULE-3113 Service should do onward routing, response-routers and
105: // reply-to
106:
107: // this is the request event
108: // event = RequestContext.getEvent();
109: if (event.isStopFurtherProcessing()) {
110: logger
111: .debug("MuleEvent stop further processing has been set, no outbound routing will be performed.");
112: }
113: if (returnMessage != null
114: && !event.isStopFurtherProcessing()) {
115: if (service.getOutboundRouter().hasEndpoints()) {
116: MuleMessage outboundReturnMessage = service
117: .getOutboundRouter().route(returnMessage,
118: event.getSession(),
119: event.isSynchronous());
120: if (outboundReturnMessage != null) {
121: returnMessage = outboundReturnMessage;
122: }
123: } else {
124: logger
125: .debug("Outbound router on service '"
126: + service.getName()
127: + "' doesn't have any endpoints configured.");
128: }
129: }
130:
131: // Process Response Router
132: // TODO Alan C. - responseRouter is initialized to empty (no
133: // endpoints) in Mule 2.x, this line can be part of a solution
134: // if (returnMessage != null && service.getResponseRouter() != null
135: // && !service.getResponseRouter().getEndpoints().isEmpty())
136: if (returnMessage != null
137: && service.getResponseRouter() != null) {
138: logger.debug("Waiting for response router message");
139: returnMessage = service.getResponseRouter()
140: .getResponse(returnMessage);
141: }
142:
143: // process replyTo if there is one
144: if (returnMessage != null && replyToHandler != null) {
145: String requestor = (String) returnMessage
146: .getProperty(MuleProperties.MULE_REPLY_TO_REQUESTOR_PROPERTY);
147: if ((requestor != null && !requestor.equals(service
148: .getName()))
149: || requestor == null) {
150: replyToHandler.processReplyTo(event, returnMessage,
151: replyTo);
152: }
153: }
154:
155: // stats
156: if (statistics.isEnabled()) {
157: statistics.incSentEventSync();
158: }
159: } catch (Exception e) {
160: event.getSession().setValid(false);
161: if (e instanceof MessagingException) {
162: handleException(e);
163: } else {
164: handleException(new MessagingException(CoreMessages
165: .eventProcessingFailedFor(service.getName()),
166: event.getMessage(), e));
167: }
168:
169: if (returnMessage == null) {
170: // important that we pull event from request context here as it may
171: // have been modified
172: // (necessary to avoid scribbling between thrreads)
173: returnMessage = new DefaultMuleMessage(NullPayload
174: .getInstance(), RequestContext.getEvent()
175: .getMessage());
176: }
177: ExceptionPayload exceptionPayload = returnMessage
178: .getExceptionPayload();
179: if (exceptionPayload == null) {
180: exceptionPayload = new DefaultExceptionPayload(e);
181: }
182: returnMessage.setExceptionPayload(exceptionPayload);
183: }
184: return returnMessage;
185:
186: }
187:
188: protected void doOnEvent(MuleEvent event) {
189: try {
190: InboundEndpoint endpoint = (InboundEndpoint) event
191: .getEndpoint();
192: // dispatch the next receiver
193: event = OptimizedRequestContext.criticalSetEvent(event);
194: Object replyTo = event.getMessage().getReplyTo();
195: ReplyToHandler replyToHandler = getReplyToHandler(event
196: .getMessage(), endpoint);
197:
198: // TODO Move stats up into AbstractComponent once routing has been moved
199: // to service.
200:
201: // do stats
202: long startTime = 0;
203: if (statistics.isEnabled()) {
204: startTime = System.currentTimeMillis();
205: }
206:
207: MuleMessage result = invokeComponentInstance(event);
208:
209: if (statistics.isEnabled()) {
210: statistics.addExecutionTime(System.currentTimeMillis()
211: - startTime);
212: }
213:
214: // TODO MULE-3113 Service should do onward routing, response-routers and
215: // reply-to
216:
217: // processResponse(result, replyTo, replyToHandler);
218: event = RequestContext.getEvent();
219: if (result != null && !event.isStopFurtherProcessing()) {
220: if (service.getOutboundRouter().hasEndpoints()) {
221: service.getOutboundRouter().route(result,
222: event.getSession(), event.isSynchronous());
223: }
224: }
225:
226: // process replyTo if there is one
227: if (result != null && replyToHandler != null) {
228: String requestor = (String) result
229: .getProperty(MuleProperties.MULE_REPLY_TO_REQUESTOR_PROPERTY);
230: if ((requestor != null && !requestor.equals(service
231: .getName()))
232: || requestor == null) {
233: replyToHandler.processReplyTo(event, result,
234: replyTo);
235: }
236: }
237:
238: if (statistics.isEnabled()) {
239: statistics.incSentEventASync();
240: }
241: } catch (Exception e) {
242: event.getSession().setValid(false);
243: if (e instanceof MessagingException) {
244: handleException(e);
245: } else {
246: handleException(new MessagingException(CoreMessages
247: .eventProcessingFailedFor(service.getName()),
248: event.getMessage(), e));
249: }
250: }
251: }
252:
253: protected MuleMessage invokeComponentInstance(MuleEvent event)
254: throws Exception {
255: LifecycleAdapter componentLifecycleAdapter = null;
256: try {
257: componentLifecycleAdapter = borrowComponentLifecycleAdaptor();
258: return componentLifecycleAdapter.intercept(null);
259: } finally {
260: returnComponentLifecycleAdaptor(componentLifecycleAdapter);
261: }
262: }
263:
264: public Class getObjectType() {
265: return objectFactory.getObjectClass();
266: }
267:
268: /**
269: * Creates and initialises a new LifecycleAdaptor instance wrapped the component
270: * object instance obtained from the configured object factory.
271: *
272: * @return
273: * @throws MuleException
274: * @throws Exception
275: */
276: protected LifecycleAdapter createLifeCycleAdaptor()
277: throws MuleException, Exception {
278: LifecycleAdapter lifecycleAdapter;
279: if (lifecycleAdapterFactory != null) {
280: // Custom lifecycleAdapterFactory set on component
281: lifecycleAdapter = lifecycleAdapterFactory.create(
282: objectFactory.getInstance(), this ,
283: entryPointResolverSet);
284: } else {
285: // Inherit lifecycleAdapterFactory from model
286: lifecycleAdapter = service.getModel()
287: .getLifecycleAdapterFactory().create(
288: objectFactory.getInstance(), this ,
289: entryPointResolverSet);
290: }
291: lifecycleAdapter.initialise();
292: return lifecycleAdapter;
293: }
294:
295: protected abstract LifecycleAdapter borrowComponentLifecycleAdaptor()
296: throws Exception;
297:
298: protected abstract void returnComponentLifecycleAdaptor(
299: LifecycleAdapter lifecycleAdapter) throws Exception;
300:
301: // @Override
302: protected void doInitialise() throws InitialisationException {
303: if (objectFactory == null) {
304: throw new InitialisationException(CoreMessages
305: .objectIsNull("object factory"), this );
306: }
307: // If this component was configured with spring the objectFactory instance
308: // has already been initialised, yet if this component was no configured with
309: // spring then the objectFactory is still uninitialised so we need to
310: // initialise it here.
311: objectFactory.initialise();
312: }
313:
314: // @Override
315: protected void doStart() throws MuleException {
316: // We need to resolve entry point resolvers here rather than in initialise()
317: // because when configuring with spring, although the service has been
318: // injected and is available the injected service construction has not been
319: // completed and model is still in null.
320: if (entryPointResolverSet == null) {
321: entryPointResolverSet = service.getModel()
322: .getEntryPointResolverSet();
323: }
324: }
325:
326: // @Override
327: protected void doStop() throws MuleException {
328: // TODO no-op
329: }
330:
331: // @Override
332: protected void doDispose() {
333: // TODO This can't be implemented currently because AbstractService allows
334: // disposed services to be re-initialised, and re-use of a disposed object
335: // factory is not possible
336: // objectFactory.dispose();
337: }
338:
339: public EntryPointResolverSet getEntryPointResolverSet() {
340: return entryPointResolverSet;
341: }
342:
343: public NestedRouterCollection getNestedRouter() {
344: return nestedRouter;
345: }
346:
347: public void setEntryPointResolverSet(
348: EntryPointResolverSet entryPointResolverSet) {
349: this .entryPointResolverSet = entryPointResolverSet;
350: }
351:
352: public void setNestedRouter(NestedRouterCollection nestedRouter) {
353: this .nestedRouter = nestedRouter;
354: }
355:
356: /**
357: * Allow for incremental addition of resolvers by for example the spring-config
358: * module
359: *
360: * @param entryPointResolvers Resolvers to add
361: */
362: public void setEntryPointResolvers(Collection entryPointResolvers) {
363: if (null == entryPointResolverSet) {
364: entryPointResolverSet = new DefaultEntryPointResolverSet();
365: }
366: for (Iterator resolvers = entryPointResolvers.iterator(); resolvers
367: .hasNext();) {
368: entryPointResolverSet
369: .addEntryPointResolver((EntryPointResolver) resolvers
370: .next());
371: }
372: }
373:
374: public ObjectFactory getObjectFactory() {
375: return objectFactory;
376: }
377:
378: public void setObjectFactory(ObjectFactory objectFactory) {
379: this .objectFactory = objectFactory;
380: }
381:
382: public LifecycleAdapterFactory getLifecycleAdapterFactory() {
383: return lifecycleAdapterFactory;
384: }
385:
386: public void setLifecycleAdapterFactory(
387: LifecycleAdapterFactory lifecycleAdapterFactory) {
388: this.lifecycleAdapterFactory = lifecycleAdapterFactory;
389: }
390:
391: }
|