View Javadoc

1   /*
2    * $Id: AbstractService.java 12247 2008-07-07 21:25:01Z dfeist $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.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.service;
12  
13  import org.mule.DefaultMuleMessage;
14  import org.mule.OptimizedRequestContext;
15  import org.mule.api.MessagingException;
16  import org.mule.api.MuleContext;
17  import org.mule.api.MuleEvent;
18  import org.mule.api.MuleException;
19  import org.mule.api.MuleMessage;
20  import org.mule.api.component.Component;
21  import org.mule.api.config.MuleProperties;
22  import org.mule.api.endpoint.ImmutableEndpoint;
23  import org.mule.api.endpoint.InboundEndpoint;
24  import org.mule.api.endpoint.OutboundEndpoint;
25  import org.mule.api.lifecycle.InitialisationException;
26  import org.mule.api.model.Model;
27  import org.mule.api.model.ModelException;
28  import org.mule.api.routing.InboundRouterCollection;
29  import org.mule.api.routing.NestedRouterCollection;
30  import org.mule.api.routing.OutboundRouterCollection;
31  import org.mule.api.routing.ResponseRouterCollection;
32  import org.mule.api.service.Service;
33  import org.mule.api.service.ServiceException;
34  import org.mule.api.transport.DispatchException;
35  import org.mule.api.transport.MessageReceiver;
36  import org.mule.api.transport.ReplyToHandler;
37  import org.mule.component.simple.PassThroughComponent;
38  import org.mule.config.i18n.CoreMessages;
39  import org.mule.config.i18n.MessageFactory;
40  import org.mule.context.notification.ServiceNotification;
41  import org.mule.management.stats.ServiceStatistics;
42  import org.mule.routing.inbound.DefaultInboundRouterCollection;
43  import org.mule.routing.inbound.InboundPassThroughRouter;
44  import org.mule.routing.nested.DefaultNestedRouterCollection;
45  import org.mule.routing.outbound.DefaultOutboundRouterCollection;
46  import org.mule.routing.outbound.OutboundPassThroughRouter;
47  import org.mule.routing.response.DefaultResponseRouterCollection;
48  import org.mule.transport.AbstractConnector;
49  import org.mule.util.concurrent.WaitableBoolean;
50  
51  import java.beans.ExceptionListener;
52  import java.util.ArrayList;
53  import java.util.Iterator;
54  import java.util.List;
55  
56  import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
57  
58  import org.apache.commons.logging.Log;
59  import org.apache.commons.logging.LogFactory;
60  
61  /**
62   * A base implementation for all UMOComponents in Mule
63   */
64  public abstract class AbstractService implements Service
65  {
66      
67      /**
68       * logger used by this class
69       */
70      protected transient Log logger = LogFactory.getLog(getClass());
71  
72      protected ServiceStatistics stats = null;
73  
74      /**
75       * Determines if the service has been stopped
76       */
77      protected AtomicBoolean stopped = new AtomicBoolean(true);
78  
79      /**
80       * Determines whether stop has been called and is still in progress
81       */
82      protected WaitableBoolean stopping = new WaitableBoolean(false);
83  
84      /**
85       * Determines if the service has been initilised
86       */
87      protected AtomicBoolean initialised = new AtomicBoolean(false);
88  
89      /**
90       * The model in which this service is registered
91       */
92      protected Model model;
93  
94      /**
95       * Determines if the service has been paused
96       */
97      protected WaitableBoolean paused = new WaitableBoolean(false);
98  
99      protected MuleContext muleContext;
100 
101     /**
102      * The initial states that the service can be started in
103      */
104     public static final String INITIAL_STATE_STOPPED = "stopped";
105     public static final String INITIAL_STATE_STARTED = "started";
106     public static final String INITIAL_STATE_PAUSED = "paused";
107 
108     /**
109      * The exception strategy used by the service.
110      */
111     protected ExceptionListener exceptionListener;
112 
113     /**
114      * The service's name
115      */
116     protected String name;
117 
118     protected InboundRouterCollection inboundRouter = new DefaultInboundRouterCollection();
119 
120     protected OutboundRouterCollection outboundRouter = new DefaultOutboundRouterCollection();
121 
122     protected NestedRouterCollection nestedRouter = new DefaultNestedRouterCollection();
123 
124     protected ResponseRouterCollection responseRouter = new DefaultResponseRouterCollection();
125 
126     /**
127      * Determines the initial state of this service when the model starts. Can be
128      * 'stopped' or 'started' (default)
129      */
130     protected String initialState = INITIAL_STATE_STARTED;
131 
132     /**
133      * Indicates whether a service has passed its initial startup state.
134      */
135     private AtomicBoolean beyondInitialState = new AtomicBoolean(false);
136 
137     // Default component to use if one is not configured.
138     // TODO MULE-3113 This should not really be needed as to implement bridging we should
139     // should just increment a 'bridged' counter and sent the event straight to
140     // outbound router collection. Currently it's the Component that routes events
141     // onto the outbound router collection so this default implementation is needed.
142     // It would be beneficial to differenciate between component invocations and
143     // events that are bridged but currently everything is an invocation.
144     protected Component component = new PassThroughComponent();
145 
146     /**
147      * For Spring only
148      */
149     public AbstractService()
150     {
151         // nop
152     }
153 
154     /**
155      * Initialise the service. The service will first create a Mule UMO from the
156      * UMODescriptor and then initialise a pool based on the attributes in the
157      * UMODescriptor.
158      *
159      * @throws org.mule.api.lifecycle.InitialisationException
160      *          if the service fails
161      *          to initialise
162      */
163     public final synchronized void initialise() throws InitialisationException
164     {
165         if (initialised.get())
166         {
167             throw new InitialisationException(CoreMessages.objectAlreadyInitialised("Service '" + name + "'"), this);
168         }
169         // Ensure Component has service instance and is initialised. If the component
170         // was configured with spring and is therefore in the registry it will get
171         // started automatically, if it was set on the service directly then it won't
172         // be started automatically. So to be sure we start it here.
173         component.setService(this);
174         component.initialise();
175 
176         if (inboundRouter == null)
177         {
178             // Create Default routes that route to the default inbound and
179             // outbound endpoints
180             inboundRouter = new DefaultInboundRouterCollection();
181             // TODO MULE-2102 This should be configured in the default template.
182             inboundRouter.addRouter(new InboundPassThroughRouter());
183         }
184         if (outboundRouter == null)
185         {
186             outboundRouter = new DefaultOutboundRouterCollection();
187             // TODO MULE-2102 This should be configured in the default template.
188             outboundRouter.addRouter(new OutboundPassThroughRouter());
189         }
190         if (responseRouter == null)
191         {
192             responseRouter = new DefaultResponseRouterCollection();
193         }
194 
195         if (exceptionListener == null)
196         {
197             //By default us the model Exception Listener
198             exceptionListener = getModel().getExceptionListener();
199 //            // TODO MULE-2102 This should be configured in the default template.
200 //            exceptionListener = new DefaultServiceExceptionStrategy(this);
201 //            ((MuleContextAware) exceptionListener).setMuleContext(muleContext);
202 //            ((Initialisable) exceptionListener).initialise();
203         }
204 
205         doInitialise();
206 
207         // initialise statistics
208         stats = createStatistics();
209 
210         stats.setEnabled(muleContext.getStatistics().isEnabled());
211         muleContext.getStatistics().add(stats);
212         stats.setOutboundRouterStat(outboundRouter.getStatistics());
213         stats.setInboundRouterStat(inboundRouter.getStatistics());
214         stats.setComponentStat(component.getStatistics());
215 
216         initialised.set(true);
217         fireServiceNotification(ServiceNotification.SERVICE_INITIALISED);
218     }
219 
220     protected ServiceStatistics createStatistics()
221     {
222         return new ServiceStatistics(name);
223     }
224 
225     protected void fireServiceNotification(int action)
226     {
227         muleContext.fireNotification(new ServiceNotification(this, action));
228     }
229 
230     public void forceStop() throws MuleException
231     {
232         if (!stopped.get())
233         {
234             logger.debug("Stopping Service");
235             stopping.set(true);
236             fireServiceNotification(ServiceNotification.SERVICE_STOPPING);
237             doForceStop();
238             stopped.set(true);
239             stopping.set(false);
240             fireServiceNotification(ServiceNotification.SERVICE_STOPPED);
241         }
242     }
243 
244     public void stop() throws MuleException
245     {
246         if (!stopped.get())
247         {
248             logger.debug("Stopping Service");
249             stopping.set(true);
250             fireServiceNotification(ServiceNotification.SERVICE_STOPPING);
251 
252             // Unregister Listeners for the service
253             unregisterListeners();
254             
255             component.stop();
256 
257             doStop();
258             stopped.set(true);
259             fireServiceNotification(ServiceNotification.SERVICE_STOPPED);
260             logger.info("Mule Service " + name + " has been stopped successfully");
261         }
262     }
263 
264     public void start() throws MuleException
265     {
266         // TODO If Service is uninitialised when start is called should we initialise
267         // or throw an exception?
268         if (!initialised.get())
269         {
270             throw new IllegalStateException("Cannot start an unitialised service.");
271         }
272         if (isStarted())
273         {
274             logger.info("Service is already started: " + name);
275         }
276         else
277         {
278             if (initialState.equals(AbstractService.INITIAL_STATE_STOPPED))
279             {
280                 logger.info("stopped");
281             }
282             if (!beyondInitialState.get() && initialState.equals(AbstractService.INITIAL_STATE_STOPPED))
283             {
284                 logger.info("Service " + name + " has not been started (initial state = 'stopped')");
285             }
286             else if (!beyondInitialState.get() && initialState.equals(AbstractService.INITIAL_STATE_PAUSED))
287             {
288                 start(/*startPaused*/true);
289                 logger.info("Service " + name + " has been started and paused (initial state = 'paused')");
290             }
291             else
292             {
293                 start(/*startPaused*/false);
294                 logger.info("Service " + name + " has been started successfully");
295             }
296             beyondInitialState.set(true);
297         }
298     }
299 
300     /**
301      * Starts a Mule Service.
302      *
303      * @param startPaused - Start service in a "paused" state (messages are
304      *                    received but not processed).
305      */
306     protected void start(boolean startPaused) throws MuleException
307     {
308 
309         // Ensure Component is started. If component was configured with spring and
310         // is therefore in the registry it will get started automatically, if it was
311         // set on the service directly then it won't be started automatically. So to
312         // be sure we start it here.
313         component.start();
314 
315         // Create the receivers for the service but do not start them yet.
316         registerListeners();
317 
318         // We connect the receivers _before_ starting the service because there may
319         // be
320         // some initialization required for the service which needs to have them
321         // connected.
322         // For example, the org.mule.transport.soap.glue.GlueMessageReceiver adds
323         // InitialisationCallbacks within its doConnect() method (see MULE-804).
324         connectListeners();
325 
326         // Start (and pause) the service.
327         if (stopped.get())
328         {
329             stopped.set(false);
330             paused.set(false);
331             doStart();
332         }
333         fireServiceNotification(ServiceNotification.SERVICE_STARTED);
334         if (startPaused)
335         {
336             pause();
337         }
338 
339         // We start the receivers _after_ starting the service because if a message
340         // gets routed to the service before it is started,
341         // org.mule.model.AbstractComponent.dispatchEvent() will throw a
342         // ServiceException with message COMPONENT_X_IS_STOPPED (see MULE-526).
343         startListeners();
344     }
345 
346     /**
347      * Pauses event processing for a single Mule Service. Unlike stop(), a paused
348      * service will still consume messages from the underlying transport, but those
349      * messages will be queued until the service is resumed.
350      */
351     public final void pause() throws MuleException
352     {
353         doPause();
354         paused.set(true);
355         fireServiceNotification(ServiceNotification.SERVICE_PAUSED);
356         logger.info("Mule Service " + name + " has been paused successfully");
357     }
358 
359     /**
360      * Resumes a single Mule Service that has been paused. If the service is not
361      * paused nothing is executed.
362      */
363     public final void resume() throws MuleException
364     {
365         doResume();
366         paused.set(false);
367         fireServiceNotification(ServiceNotification.SERVICE_RESUMED);
368         logger.info("Mule Service " + name + " has been resumed successfully");
369     }
370 
371     /**
372      * Determines if the service is in a paused state
373      *
374      * @return True if the service is in a paused state, false otherwise
375      */
376     public boolean isPaused()
377     {
378         return paused.get();
379     }
380 
381     /**
382      * Custom components can execute code necessary to put the service in a paused
383      * state here. If a developer overloads this method the doResume() method MUST
384      * also be overloaded to avoid inconsistent state in the service
385      *
386      * @throws MuleException
387      */
388     protected void doPause() throws MuleException
389     {
390         // template method
391     }
392 
393     /**
394      * Custom components can execute code necessary to resume a service once it has
395      * been paused If a developer overloads this method the doPause() method MUST
396      * also be overloaded to avoid inconsistent state in the service
397      *
398      * @throws MuleException
399      */
400     protected void doResume() throws MuleException
401     {
402         // template method
403     }
404 
405     public final void dispose()
406     {
407         try
408         {
409             if (!stopped.get())
410             {
411                 stop();
412             }
413         }
414         catch (MuleException e)
415         {
416             // TODO MULE-863: If this is an error, do something!
417             logger.error("Failed to stop service: " + name, e);
418         }
419         doDispose();
420         component.dispose();
421         initialised.set(false);
422         fireServiceNotification(ServiceNotification.SERVICE_DISPOSED);
423         muleContext.getStatistics().remove(stats);
424     }
425 
426     public ServiceStatistics getStatistics()
427     {
428         return stats;
429     }
430 
431     public void dispatchEvent(MuleEvent event) throws MuleException
432     {
433         if (stopping.get() || stopped.get())
434         {
435             throw new ServiceException(
436                     CoreMessages.componentIsStopped(name),
437                     event.getMessage(), this);
438         }
439 
440         try
441         {
442             waitIfPaused(event);
443         }
444         catch (InterruptedException e)
445         {
446             throw new ServiceException(event.getMessage(), this, e);
447         }
448 
449         // Dispatching event to an inbound endpoint
450         // in the DefaultMuleSession#dispatchEvent
451         ImmutableEndpoint endpoint = event.getEndpoint();
452 
453         if (endpoint instanceof OutboundEndpoint)
454         {
455             try
456             {
457                 ((OutboundEndpoint) endpoint).dispatch(event);
458             }
459             catch (Exception e)
460             {
461                 throw new DispatchException(event.getMessage(), event.getEndpoint(), e);
462             }
463 
464             return;
465         }
466 
467         // Dispatching event to the service
468         if (stats.isEnabled())
469         {
470             stats.incReceivedEventASync();
471         }
472 
473         if (logger.isDebugEnabled())
474         {
475             logger.debug("Service: " + name + " has received asynchronous event on: "
476                     + event.getEndpoint().getEndpointURI());
477         }
478 
479         doDispatch(event);
480     }
481 
482     public MuleMessage sendEvent(MuleEvent event) throws MuleException
483     {
484         if (stopping.get() || stopped.get())
485         {
486             throw new ServiceException(
487                     CoreMessages.componentIsStopped(name),
488                     event.getMessage(), this);
489         }
490 
491         try
492         {
493             waitIfPaused(event);
494         }
495         catch (InterruptedException e)
496         {
497             throw new ServiceException(event.getMessage(), this, e);
498         }
499 
500         if (stats.isEnabled())
501         {
502             stats.incReceivedEventSync();
503         }
504         if (logger.isDebugEnabled())
505         {
506             logger.debug("Service: " + name + " has received synchronous event on: "
507                     + event.getEndpoint().getEndpointURI());
508         }
509         event = OptimizedRequestContext.unsafeSetEvent(event);
510         return doSend(event);
511     }
512 
513     /**
514      * Called before an event is sent or dispatched to a service, it will block
515      * until resume() is called. Users can override this method if they want to
516      * handle pausing differently e.g. implement a store and forward policy
517      *
518      * @param event the current event being passed to the service
519      * @throws InterruptedException if the thread is interrupted
520      */
521     protected void waitIfPaused(MuleEvent event) throws InterruptedException
522     {
523         if (logger.isDebugEnabled() && paused.get())
524         {
525             logger.debug("Service: " + name
526                     + " is paused. Blocking call until resume is called");
527         }
528         paused.whenFalse(null);
529     }
530 
531     /**
532      * @return the Mule descriptor name which is associated with the service
533      */
534     public String getName()
535     {
536         return name;
537     }
538 
539     /*
540      * (non-Javadoc)
541      * 
542      * @see java.lang.Object#toString()
543      */
544     public String toString()
545     {
546         return getName();
547     }
548 
549     public boolean isStopped()
550     {
551         return stopped.get();
552     }
553 
554     public boolean isStopping()
555     {
556         return stopping.get();
557     }
558 
559     protected void handleException(Exception e)
560     {
561         exceptionListener.exceptionThrown(e);
562     }
563 
564     protected void doForceStop() throws MuleException
565     {
566         // template method
567     }
568 
569     protected void doStop() throws MuleException
570     {
571         // template method
572     }
573 
574     protected void doStart() throws MuleException
575     {
576         // template method
577     }
578 
579     protected void doDispose()
580     {
581         // template method
582     }
583 
584     protected void doInitialise() throws InitialisationException
585     {
586         // template method
587     }
588 
589     public boolean isStarted()
590     {
591         return !stopped.get();
592     }
593 
594     protected abstract MuleMessage doSend(MuleEvent event) throws MuleException;
595 
596     protected abstract void doDispatch(MuleEvent event) throws MuleException;
597 
598     protected void registerListeners() throws MuleException
599     {
600         InboundEndpoint endpoint;
601         List endpoints = getIncomingEndpoints();
602 
603         for (Iterator it = endpoints.iterator(); it.hasNext();)
604         {
605             endpoint = (InboundEndpoint) it.next();
606             try
607             {
608                 endpoint.getConnector().registerListener(this, endpoint);
609             }
610             catch (MuleException e)
611             {
612                 throw e;
613             }
614             catch (Exception e)
615             {
616                 throw new ModelException(
617                         CoreMessages.failedtoRegisterOnEndpoint(name, endpoint.getEndpointURI()), e);
618             }
619         }
620     }
621 
622     protected void unregisterListeners() throws MuleException
623     {
624         InboundEndpoint endpoint;
625         List endpoints = getIncomingEndpoints();
626 
627         for (Iterator it = endpoints.iterator(); it.hasNext();)
628         {
629             endpoint = (InboundEndpoint) it.next();
630             try
631             {
632                 endpoint.getConnector().unregisterListener(this, endpoint);
633             }
634             catch (MuleException e)
635             {
636                 throw e;
637             }
638             catch (Exception e)
639             {
640                 throw new ModelException(
641                         CoreMessages.failedToUnregister(name, endpoint.getEndpointURI()), e);
642             }
643         }
644     }
645 
646     protected void startListeners() throws MuleException
647     {
648         InboundEndpoint endpoint;
649         List endpoints = getIncomingEndpoints();
650 
651         for (Iterator it = endpoints.iterator(); it.hasNext();)
652         {
653             endpoint = (InboundEndpoint) it.next();
654             MessageReceiver receiver = ((AbstractConnector) endpoint.getConnector()).getReceiver(this,
655                     endpoint);
656             if (receiver != null && endpoint.getConnector().isStarted()
657                     && endpoint.getInitialState().equals(ImmutableEndpoint.INITIAL_STATE_STARTED))
658             {
659                 receiver.start();
660             }
661         }
662     }
663 
664     // This is not called by anything?!
665     protected void stopListeners() throws MuleException
666     {
667         InboundEndpoint endpoint;
668         List endpoints = getIncomingEndpoints();
669 
670         for (Iterator it = endpoints.iterator(); it.hasNext();)
671         {
672             endpoint = (InboundEndpoint) it.next();
673             MessageReceiver receiver = ((AbstractConnector) endpoint.getConnector()).getReceiver(this,
674                     endpoint);
675             if (receiver != null)
676             {
677                 receiver.stop();
678             }
679         }
680     }
681 
682     protected void connectListeners() throws MuleException
683     {
684         InboundEndpoint endpoint;
685         List endpoints = getIncomingEndpoints();
686 
687         for (Iterator it = endpoints.iterator(); it.hasNext();)
688         {
689             endpoint = (InboundEndpoint) it.next();
690             MessageReceiver receiver = ((AbstractConnector) endpoint.getConnector()).getReceiver(this,
691                     endpoint);
692             if (receiver != null)
693             {
694                 try
695                 {
696                     receiver.connect();
697                 }
698                 catch (Exception e)
699                 {
700                     throw new ModelException(
701                             MessageFactory.createStaticMessage("Failed to connect listener "
702                                     + receiver + " for endpoint " + endpoint.getName()),
703                             e);
704                 }
705             }
706         }
707     }
708 
709     protected void disconnectListeners() throws MuleException
710     {
711         InboundEndpoint endpoint;
712         List endpoints = getIncomingEndpoints();
713 
714         for (Iterator it = endpoints.iterator(); it.hasNext();)
715         {
716             endpoint = (InboundEndpoint) it.next();
717             MessageReceiver receiver = ((AbstractConnector) endpoint.getConnector()).getReceiver(this,
718                     endpoint);
719             if (receiver != null)
720             {
721                 try
722                 {
723                     receiver.disconnect();
724                 }
725                 catch (Exception e)
726                 {
727                     throw new ModelException(
728                             MessageFactory.createStaticMessage("Failed to disconnect listener "
729                                     + receiver + " for endpoint " + endpoint.getName()),
730                             e);
731                 }
732             }
733         }
734     }
735 
736     /**
737      * Returns a list of all incoming endpoints on a service.
738      */
739     protected List getIncomingEndpoints()
740     {
741         List endpoints = new ArrayList();
742 
743         // Add inbound endpoints
744         endpoints.addAll(inboundRouter.getEndpoints());
745 
746         // Add response endpoints
747         if (responseRouter != null
748                 && responseRouter.getEndpoints() != null)
749         {
750             endpoints.addAll(responseRouter.getEndpoints());
751         }
752         return endpoints;
753     }
754 
755     public void setMuleContext(MuleContext context)
756     {
757         this.muleContext = context;
758     }
759 
760     // /////////////////////////////////////////////////////////////////////////////////////////
761     // Getters and Setters
762     // /////////////////////////////////////////////////////////////////////////////////////////
763 
764     public Model getModel()
765     {
766         return model;
767     }
768 
769     public void setModel(Model model)
770     {
771         this.model = model;
772     }
773 
774     public ExceptionListener getExceptionListener()
775     {
776         return exceptionListener;
777     }
778 
779     public void setExceptionListener(ExceptionListener exceptionListener)
780     {
781         this.exceptionListener = exceptionListener;
782     }
783 
784     public InboundRouterCollection getInboundRouter()
785     {
786         return inboundRouter;
787     }
788 
789     public void setInboundRouter(InboundRouterCollection inboundRouter)
790     {
791         this.inboundRouter = inboundRouter;
792     }
793 
794     public OutboundRouterCollection getOutboundRouter()
795     {
796         return outboundRouter;
797     }
798 
799     public void setOutboundRouter(OutboundRouterCollection outboundRouter)
800     {
801         this.outboundRouter = outboundRouter;
802     }
803 
804     public ResponseRouterCollection getResponseRouter()
805     {
806         return responseRouter;
807     }
808 
809     public void setResponseRouter(ResponseRouterCollection responseRouter)
810     {
811         this.responseRouter = responseRouter;
812     }
813 
814     public String getInitialState()
815     {
816         return initialState;
817     }
818 
819     public void setInitialState(String initialState)
820     {
821         this.initialState = initialState;
822     }
823 
824     public void setName(String name)
825     {
826         this.name = name;
827     }
828 
829     public Component getComponent()
830     {
831         return component;
832     }
833 
834     public void setComponent(Component component)
835     {
836         this.component = component;
837         this.component.setService(this);
838     }
839 
840     protected void processReplyTo(MuleEvent event, MuleMessage result, ReplyToHandler replyToHandler, Object replyTo)
841         throws MuleException
842     {
843         if (result != null && replyToHandler != null)
844         {
845             String requestor = (String) result.getProperty(MuleProperties.MULE_REPLY_TO_REQUESTOR_PROPERTY);
846             if ((requestor != null && !requestor.equals(getName())) || requestor == null)
847             {
848                 replyToHandler.processReplyTo(event, result, replyTo);
849             }
850         }
851     }
852 
853     protected ReplyToHandler getReplyToHandler(MuleMessage message, InboundEndpoint endpoint)
854     {
855         Object replyTo = message.getReplyTo();
856         ReplyToHandler replyToHandler = null;
857         if (replyTo != null)
858         {
859             replyToHandler = ((AbstractConnector) endpoint.getConnector()).getReplyToHandler();
860             // Use the response transformer for the event if one is set
861             if (endpoint.getResponseTransformers() != null)
862             {
863                 replyToHandler.setTransformers(endpoint.getResponseTransformers());
864             }
865         }
866         return replyToHandler;
867     }
868 
869     // This method is used when the service invoked asynchronously. It should really
870     // be used independantly of if the service is invoked asynchronously when we are
871     // using an out-in or out-optional-in outbound message exchange pattern
872     protected void dispatchToOutboundRouter(MuleEvent event, MuleMessage result) throws MessagingException
873     {
874         if (event.isStopFurtherProcessing())
875         {
876             logger.debug("MuleEvent stop further processing has been set, no outbound routing will be performed.");
877         }
878         if (result != null && !event.isStopFurtherProcessing())
879         {
880             if (getOutboundRouter().hasEndpoints())
881             {
882                 // Here we can use the same message instance because there is no inbound response.
883                 getOutboundRouter().route(result, event.getSession(), event.isSynchronous());
884             }
885         }
886     }
887 
888     // This method is used when the service invoked synchronously. It should really
889     // be used independantly of if the service is invoked synchronously when we are
890     // using an out-only outbound message exchange pattern
891     protected MuleMessage sendToOutboundRouter(MuleEvent event, MuleMessage result) throws MessagingException
892     {
893         if (event.isStopFurtherProcessing())
894         {
895             logger.debug("MuleEvent stop further processing has been set, no outbound routing will be performed.");
896         }
897         if (result != null && !event.isStopFurtherProcessing())
898         {
899             if (getOutboundRouter().hasEndpoints())
900             {
901                 // Here we need to use a copy of the message instance because there
902                 // is an inbound response so that transformers executed as part of
903                 // the outbound phase do not affect the inbound response. MULE-3307
904                 MuleMessage outboundReturnMessage = getOutboundRouter().route(new DefaultMuleMessage(result), event.getSession(),
905                     event.isSynchronous());
906                 if (outboundReturnMessage != null)
907                 {
908                     result = outboundReturnMessage;
909                 }
910             }
911             else
912             {
913                 logger.debug("Outbound router on service '" + getName() + "' doesn't have any endpoints configured.");
914             }
915         }
916         return result;
917     }
918 
919     protected MuleMessage processAsyncReplyRouter(MuleMessage result) throws MuleException
920     {
921         if (result != null && getResponseRouter() != null)
922         {
923             logger.debug("Waiting for response router message");
924             result = getResponseRouter().getResponse(result);
925         }
926         return result;
927     }
928 
929     public MuleContext getMuleContext()
930     {
931         return muleContext;
932     }
933 
934 }