View Javadoc

1   /*
2    * $Id: RetryPolicyDefinitionParser.java 22132 2011-06-06 23:28:49Z dzapata $
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  package org.mule.config.spring.parsers.specific;
11  
12  import org.mule.api.config.MuleProperties;
13  import org.mule.config.spring.parsers.generic.OptionalChildDefinitionParser;
14  import org.mule.retry.async.AsynchronousRetryTemplate;
15  
16  import org.apache.commons.lang.StringUtils;
17  import org.springframework.beans.factory.config.BeanDefinition;
18  import org.springframework.beans.factory.config.BeanDefinitionHolder;
19  import org.springframework.beans.factory.config.RuntimeBeanReference;
20  import org.springframework.beans.factory.support.BeanDefinitionBuilder;
21  import org.springframework.beans.factory.xml.ParserContext;
22  import org.w3c.dom.Element;
23  
24  /**
25   * Allows retry policies to be children of connector elements <i>or</i> the <mule-configuration> element.
26   */
27  public class RetryPolicyDefinitionParser extends OptionalChildDefinitionParser
28  {
29      boolean asynchronous = false;
30  
31      public RetryPolicyDefinitionParser()
32      {
33          super("retryPolicyTemplate");
34      }
35  
36      public RetryPolicyDefinitionParser(Class clazz)
37      {
38          super("retryPolicyTemplate", clazz);
39      }
40  
41      @Override
42      protected boolean isChild(Element element, ParserContext parserContext, BeanDefinitionBuilder builder)
43      {
44          if (getParentBeanName(element).equals(MuleProperties.OBJECT_MULE_CONFIGURATION))
45          {
46              element.setAttribute(ATTRIBUTE_ID, MuleProperties.OBJECT_DEFAULT_RETRY_POLICY_TEMPLATE);
47              return false;
48          }
49          else
50          {
51              return true;
52          }
53      }
54  
55      @Override
56      protected void preProcess(Element element)
57      {
58          super.preProcess(element);
59  
60          // Is this an asynchronous retry policy?
61          asynchronous = !Boolean.parseBoolean(element.getAttribute("blocking"));
62          element.removeAttribute("blocking");
63  
64          // Deprecated attribute from 2.x kept for backwards-compatibility.  Remove for the next major release.
65          if (StringUtils.isNotEmpty(element.getAttribute("asynchronous")))
66          {
67              asynchronous = Boolean.parseBoolean(element.getAttribute("asynchronous"));
68              element.removeAttribute("asynchronous");            
69              return;
70          }
71      }
72  
73      /**
74       * The BDP magic inside this method will transform this simple config:
75       *
76       *      <test:connector name="testConnector8">
77       *          <ee:reconnect blocking="false" count="5" frequency="1000"/>
78       *      </test:connector>
79       *
80       * into this equivalent config, because of the attribute asynchronous="true":
81       *
82       *      <test:connector name="testConnector8">
83       *          <spring:property name="retryPolicyTemplate">
84       *              <spring:bean class="org.mule.retry.async.AsynchronousRetryTemplate">
85       *                  <spring:constructor-arg>
86       *                      <spring:bean name="delegate" class="org.mule.retry.policies.SimpleRetryPolicyTemplate">
87       *                          <spring:property name="count" value="5"/>
88       *                          <spring:property name="frequency" value="1000"/>
89       *                      </spring:bean>
90       *                  </spring:constructor-arg>
91       *              </spring:bean>
92       *          </spring:property>
93       *      </test:connector>
94       */
95      @Override
96      protected void parseChild(Element element, ParserContext parserContext, BeanDefinitionBuilder builder)
97      {
98          super.parseChild(element, parserContext, builder);
99  
100         if (asynchronous)
101         {
102             // Create the AsynchronousRetryTemplate as a wrapper bean
103             BeanDefinitionBuilder bdb = BeanDefinitionBuilder.genericBeanDefinition(AsynchronousRetryTemplate.class);
104             // Generate a bean name
105             String asynchWrapperName = parserContext.getReaderContext().generateBeanName(bdb.getBeanDefinition());
106             // Pass in the retry policy as a constructor argument
107             String retryPolicyName = getBeanName(element);
108             bdb.addConstructorArgReference(retryPolicyName);
109             // Register the new bean
110             BeanDefinitionHolder holder = new BeanDefinitionHolder(bdb.getBeanDefinition(), asynchWrapperName);
111             registerBeanDefinition(holder, parserContext.getRegistry());
112 
113             // Set the AsynchronousRetryTemplate wrapper bean on the retry policy's parent instead of the retry policy itself
114             BeanDefinition parent = parserContext.getRegistry().getBeanDefinition(getParentBeanName(element));
115             parent.getPropertyValues().addPropertyValue(getPropertyName(element), new RuntimeBeanReference(asynchWrapperName));
116         }
117     }
118 }