View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.routing.outbound;
8   
9   import org.mule.DefaultMuleMessage;
10  import org.mule.api.MuleEvent;
11  import org.mule.api.MuleMessage;
12  import org.mule.api.MuleMessageCollection;
13  import org.mule.api.MuleSession;
14  import org.mule.api.endpoint.OutboundEndpoint;
15  import org.mule.module.xml.routing.XmlMessageSplitter;
16  import org.mule.tck.MuleTestUtils;
17  import org.mule.tck.junit4.AbstractMuleContextTestCase;
18  import org.mule.util.IOUtils;
19  
20  import com.mockobjects.constraint.Constraint;
21  import com.mockobjects.dynamic.Mock;
22  
23  import java.util.HashMap;
24  import java.util.Map;
25  
26  import org.dom4j.Document;
27  import org.dom4j.DocumentHelper;
28  import org.junit.Test;
29  
30  import static org.junit.Assert.assertEquals;
31  import static org.junit.Assert.assertNotNull;
32  import static org.junit.Assert.assertTrue;
33  import static org.junit.Assert.fail;
34  
35  public class RoundRobinXmlSplitterTestCase extends AbstractMuleContextTestCase
36  {
37      private OutboundEndpoint endpoint1;
38      private OutboundEndpoint endpoint2;
39      private OutboundEndpoint endpoint3;
40      private OutboundEndpoint endpoint4;
41      private OutboundEndpoint endpoint5;
42      private OutboundEndpoint endpoint6;
43      private Mock mockendpoint1;
44      private Mock mockendpoint2;
45      private Mock mockendpoint3;
46      private Mock mockendpoint4;
47      private Mock mockendpoint5;
48      private Mock mockendpoint6;
49      private XmlMessageSplitter asyncXmlSplitter;
50      private XmlMessageSplitter syncXmlSplitter;
51  
52      @Override
53      protected void doSetUp() throws Exception
54      {
55          // setup async targets
56          endpoint1 = getTestOutboundEndpoint("Test1Endpoint", "test://endpointUri.1");
57          endpoint2 = getTestOutboundEndpoint("Test2Endpoint", "test://endpointUri.2");
58          endpoint3 = getTestOutboundEndpoint("Test3Endpoint", "test://endpointUri.3");
59          mockendpoint1 = RouterTestUtils.getMockEndpoint(endpoint1);
60          mockendpoint2 = RouterTestUtils.getMockEndpoint(endpoint2);
61          mockendpoint3 = RouterTestUtils.getMockEndpoint(endpoint3);
62  
63          // setup sync targets
64          endpoint4 = getTestOutboundEndpoint("Test4Endpoint", "test://endpointUri.4?exchangePattern=request-response");
65          endpoint5 = getTestOutboundEndpoint("Test5Endpoint", "test://endpointUri.5?exchangePattern=request-response");
66          endpoint6 = getTestOutboundEndpoint("Test6Endpoint", "test://endpointUri.6?exchangePattern=request-response");
67          mockendpoint4 = RouterTestUtils.getMockEndpoint(endpoint4);
68          mockendpoint5 = RouterTestUtils.getMockEndpoint(endpoint5);
69          mockendpoint6 = RouterTestUtils.getMockEndpoint(endpoint6);
70  
71          // setup async splitter
72          asyncXmlSplitter = new XmlMessageSplitter();
73          asyncXmlSplitter.setValidateSchema(true);
74          asyncXmlSplitter.setExternalSchemaLocation("purchase-order.xsd");
75          asyncXmlSplitter.setMuleContext(muleContext);
76  
77          // The xml document declares a default namespace, thus
78          // we need to workaround it by specifying it both in
79          // the namespaces and in the splitExpression
80          Map namespaces = new HashMap();
81          namespaces.put("e", "http://www.example.com");
82          asyncXmlSplitter.setSplitExpression("/e:purchaseOrder/e:items/e:item");
83          asyncXmlSplitter.setNamespaces(namespaces);
84          asyncXmlSplitter.addRoute((OutboundEndpoint) mockendpoint1.proxy());
85          asyncXmlSplitter.addRoute((OutboundEndpoint) mockendpoint2.proxy());
86          asyncXmlSplitter.addRoute((OutboundEndpoint) mockendpoint3.proxy());
87  
88          // setup sync splitter
89          syncXmlSplitter = new XmlMessageSplitter();
90          syncXmlSplitter.setMuleContext(muleContext);
91          syncXmlSplitter.setValidateSchema(true);
92          syncXmlSplitter.setExternalSchemaLocation("purchase-order.xsd");
93          syncXmlSplitter.setSplitExpression("/e:purchaseOrder/e:items/e:item");
94  
95          syncXmlSplitter.setNamespaces(namespaces);
96          syncXmlSplitter.addRoute((OutboundEndpoint) mockendpoint4.proxy());
97          syncXmlSplitter.addRoute((OutboundEndpoint) mockendpoint5.proxy());
98          syncXmlSplitter.addRoute((OutboundEndpoint) mockendpoint6.proxy());
99      }
100 
101     @Test
102     public void testStringPayloadXmlMessageSplitter() throws Exception
103     {
104         String payload = IOUtils.getResourceAsString("purchase-order2.xml", getClass());
105         internalTestSuccessfulXmlSplitter(payload);
106     }
107 
108     @Test
109     public void testDom4JDocumentPayloadXmlMessageSplitter() throws Exception
110     {
111         String payload = IOUtils.getResourceAsString("purchase-order2.xml", getClass());
112         Document doc = DocumentHelper.parseText(payload);
113         internalTestSuccessfulXmlSplitter(doc);
114     }
115 
116     @Test
117     public void testByteArrayPayloadXmlMessageSplitter() throws Exception
118     {
119         String payload = IOUtils.getResourceAsString("purchase-order2.xml", getClass());
120         internalTestSuccessfulXmlSplitter(payload.getBytes());
121     }
122 
123     private void internalTestSuccessfulXmlSplitter(Object payload) throws Exception
124     {
125         Mock session = MuleTestUtils.getMockSession();
126         session.matchAndReturn("getFlowConstruct", getTestService());
127         session.matchAndReturn("setFlowConstruct", RouterTestUtils.getArgListCheckerFlowConstruct(), null);
128         MuleMessage message = new DefaultMuleMessage(payload, muleContext);
129 
130         assertTrue(asyncXmlSplitter.isMatch(message));
131         final RoundRobinXmlSplitterTestCase.ItemNodeConstraint itemNodeConstraint = new RoundRobinXmlSplitterTestCase.ItemNodeConstraint();
132         mockendpoint1.expect("process", RouterTestUtils.getArgListCheckerMuleEvent());
133         mockendpoint2.expect("process", RouterTestUtils.getArgListCheckerMuleEvent());
134         mockendpoint3.expect("process", RouterTestUtils.getArgListCheckerMuleEvent());
135         mockendpoint1.expect("process", RouterTestUtils.getArgListCheckerMuleEvent());
136         asyncXmlSplitter.route(new OutboundRoutingTestEvent(message, (MuleSession) session.proxy()));
137         mockendpoint1.verify();
138         mockendpoint2.verify();
139         mockendpoint3.verify();
140 
141         message = new DefaultMuleMessage(payload, muleContext);
142         MuleEvent event = new OutboundRoutingTestEvent(message, null);
143         assertTrue(syncXmlSplitter.isMatch(message));
144         mockendpoint4.expectAndReturn("process", RouterTestUtils.getArgListCheckerMuleEvent(), event);
145         mockendpoint5.expectAndReturn("process", RouterTestUtils.getArgListCheckerMuleEvent(), event);
146         mockendpoint6.expectAndReturn("process", RouterTestUtils.getArgListCheckerMuleEvent(), event);
147         mockendpoint4.expectAndReturn("process", RouterTestUtils.getArgListCheckerMuleEvent(), event);
148         MuleEvent result = syncXmlSplitter.route(new OutboundRoutingTestEvent(message, (MuleSession) session.proxy()));
149         MuleMessage resultMessage = result.getMessage();
150         assertNotNull(resultMessage);
151         assertNotNull(result);
152         assertTrue(resultMessage instanceof MuleMessageCollection);
153         assertEquals(4, ((MuleMessageCollection) resultMessage).size());
154         mockendpoint4.verify();
155         mockendpoint5.verify();
156         mockendpoint6.verify();
157     }
158 
159     @Test
160     public void testXsdNotFoundThrowsException() throws Exception
161     {
162         final String invalidSchemaLocation = "non-existent.xsd";
163         Mock session = MuleTestUtils.getMockSession();
164         session.matchAndReturn("getFlowConstruct", getTestService());
165 
166         XmlMessageSplitter splitter = new XmlMessageSplitter();
167         splitter.setValidateSchema(true);
168         splitter.setExternalSchemaLocation(invalidSchemaLocation);
169         splitter.setMuleContext(muleContext);
170         String payload = IOUtils.getResourceAsString("purchase-order.xml", getClass());
171 
172         MuleMessage message = new DefaultMuleMessage(payload, muleContext);
173 
174         assertTrue(splitter.isMatch(message));
175         try
176         {
177             splitter.route(new OutboundRoutingTestEvent(message, (MuleSession) session.proxy()));
178             fail("Should have thrown an exception, because XSD is not found.");
179         }
180         catch (IllegalArgumentException iaex)
181         {
182             assertTrue("Wrong exception?", iaex.getMessage().indexOf(
183                     "Couldn't find schema at " + invalidSchemaLocation) != -1);
184         }
185         session.verify();
186     }
187 
188 
189     @Test
190     public void testInvalidXmlPayloadThrowsException() throws Exception
191     {
192         Mock session = MuleTestUtils.getMockSession();
193         session.matchAndReturn("getFlowConstruct", getTestService());
194 
195         XmlMessageSplitter splitter = new XmlMessageSplitter();
196         splitter.setMuleContext(muleContext);      
197         MuleMessage message = new DefaultMuleMessage("This is not XML.", muleContext);
198 
199         try
200         {
201             splitter.route(new OutboundRoutingTestEvent(message, (MuleSession) session.proxy()));
202             fail("No exception thrown.");
203         }
204         catch (IllegalArgumentException iaex)
205         {
206             assertTrue("Wrong exception message.", iaex.getMessage().startsWith(
207                     "Failed to initialise the payload: "));
208         }
209 
210     }
211 
212     private class ItemNodeConstraint implements Constraint
213     {
214         public boolean eval(Object o)
215         {
216             final MuleMessage message = (MuleMessage) o;
217             final Object payload = message.getPayload();
218             assertTrue("Wrong class type for node.", payload instanceof Document);
219 
220             Document node = (Document) payload;
221 
222             final String partNumber = node.getRootElement().attributeValue("partNum");
223 
224             return "872-AA".equals(partNumber) || "926-AA".equals(partNumber) || "126-AA".equals(partNumber)
225                     || "226-AA".equals(partNumber);
226         }
227     }
228 }