View Javadoc

1   /*
2    * $Id: Flow.java 23059 2011-10-03 02:36:25Z pablo.lagreca $
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.construct;
12  
13  import org.mule.DefaultMuleEvent;
14  import org.mule.RequestContext;
15  import org.mule.api.MuleContext;
16  import org.mule.api.MuleEvent;
17  import org.mule.api.MuleException;
18  import org.mule.api.MuleSession;
19  import org.mule.api.endpoint.InboundEndpoint;
20  import org.mule.api.processor.MessageProcessor;
21  import org.mule.api.processor.MessageProcessorChainBuilder;
22  import org.mule.api.processor.ProcessingStrategy;
23  import org.mule.api.processor.ProcessingStrategy.StageNameSource;
24  import org.mule.construct.flow.DefaultFlowProcessingStrategy;
25  import org.mule.construct.processor.FlowConstructStatisticsMessageProcessor;
26  import org.mule.interceptor.ProcessingTimeInterceptor;
27  import org.mule.lifecycle.processor.ProcessIfStartedMessageProcessor;
28  import org.mule.management.stats.FlowConstructStatistics;
29  import org.mule.processor.strategy.AsynchronousProcessingStrategy;
30  import org.mule.routing.requestreply.AsyncReplyToPropertyRequestReplyReplier;
31  import org.mule.session.DefaultMuleSession;
32  
33  /**
34   * This implementation of {@link AbstractPipeline} adds the following functionality:
35   * <ul>
36   * <li>Rejects inbound events when Flow is not started</li>
37   * <li>Gathers statistics and processing time data</li>
38   * <li>Implements MessagePorcessor allowing direct invocation of the pipeline</li>
39   * <li>Supports the optional configuration of a {@link ProcessingStrategy} that determines how message
40   * processors are processed. The default {@link ProcessingStrategy} is {@link AsynchronousProcessingStrategy}.
41   * With this strategy when messages are received from a one-way message source and there is no current
42   * transactions message processing in another thread asynchronously.</li>
43   * </ul>
44   */
45  public class Flow extends AbstractPipeline implements MessageProcessor
46  {
47      private int stageCount = 0;
48      private int asyncCount = 0;
49  
50      public Flow(String name, MuleContext muleContext)
51      {
52          super(name, muleContext);
53          processingStrategy = new DefaultFlowProcessingStrategy();
54      }
55  
56      @Override
57      public MuleEvent process(MuleEvent event) throws MuleException
58      {
59          MuleSession calledSession = new DefaultMuleSession(event.getSession(), this);
60          MuleEvent newEvent = new DefaultMuleEvent(event.getMessage(), event, calledSession);
61          RequestContext.setEvent(newEvent);
62          try
63          {
64              MuleEvent result = pipeline.process(newEvent);
65              if (result != null)
66              {
67                  result.getMessage().release();
68              }
69              return result;
70          }
71          catch (Exception e)
72          {
73              return getExceptionListener().handleException(e, newEvent);
74          }
75          finally
76          {
77              RequestContext.setEvent(event);
78              event.getMessage().release();
79          }
80      }
81  
82      @Override
83      protected void configurePreProcessors(MessageProcessorChainBuilder builder) throws MuleException
84      {
85          super.configurePreProcessors(builder);
86          builder.chain(new ProcessIfStartedMessageProcessor(this, getLifecycleState()));
87          builder.chain(new ProcessingTimeInterceptor());
88          builder.chain(new FlowConstructStatisticsMessageProcessor());
89      }
90  
91      @Override
92      protected void configurePostProcessors(MessageProcessorChainBuilder builder) throws MuleException
93      {
94          super.configurePostProcessors(builder);
95          builder.chain(new AsyncReplyToPropertyRequestReplyReplier());
96      }
97  
98      /**
99       * @deprecated use setMessageSource(MessageSource) instead
100      */
101     @Deprecated
102     public void setEndpoint(InboundEndpoint endpoint)
103     {
104         this.messageSource = endpoint;
105     }
106 
107     @Override
108     public String getConstructType()
109     {
110         return "Flow";
111     }
112 
113     @Override
114     protected void configureStatistics()
115     {
116         if (processingStrategy instanceof AsynchronousProcessingStrategy
117             && ((AsynchronousProcessingStrategy) processingStrategy).getMaxThreads() != null)
118         {
119             statistics = new FlowConstructStatistics(getConstructType(), name,
120                 ((AsynchronousProcessingStrategy) processingStrategy).getMaxThreads());
121         }
122         else
123         {
124             statistics = new FlowConstructStatistics(getConstructType(), name);
125         }
126         statistics.setEnabled(muleContext.getStatistics().isEnabled());
127         muleContext.getStatistics().add(statistics);
128     }
129 
130     protected void configureMessageProcessors(MessageProcessorChainBuilder builder) throws MuleException
131     {
132         getProcessingStrategy().configureProcessors(getMessageProcessors(),
133             new ProcessingStrategy.StageNameSource()
134             {
135                 @Override
136                 public String getName()
137                 {
138                     return String.format("%s.stage%s", Flow.this.getName(), ++stageCount);
139                 }
140             }, builder, muleContext);
141     }
142 
143     public StageNameSource getAsyncStageNameSource()
144     {
145         return new ProcessingStrategy.StageNameSource()
146         {
147             @Override
148             public String getName()
149             {
150                 return String.format("%s.async%s", Flow.this.getName(), ++asyncCount);
151             }
152         };
153     }
154 
155     public StageNameSource getAsyncStageNameSource(final String asyncName)
156     {
157         return new ProcessingStrategy.StageNameSource()
158         {
159             @Override
160             public String getName()
161             {
162                 return String.format("%s.%s", Flow.this.getName(), asyncName);
163             }
164         };
165     }
166 
167 }