1   /*
2    * Copyright 2005-2010 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.ws.server.endpoint.adapter.method.jaxb;
18  
19  import java.io.ByteArrayOutputStream;
20  import java.io.IOException;
21  import javax.xml.bind.JAXBException;
22  import javax.xml.bind.annotation.XmlElement;
23  import javax.xml.bind.annotation.XmlRootElement;
24  import javax.xml.bind.annotation.XmlType;
25  import javax.xml.transform.Transformer;
26  import javax.xml.transform.TransformerFactory;
27  
28  import org.springframework.core.MethodParameter;
29  import org.springframework.ws.MockWebServiceMessage;
30  import org.springframework.ws.MockWebServiceMessageFactory;
31  import org.springframework.ws.WebServiceMessage;
32  import org.springframework.ws.context.DefaultMessageContext;
33  import org.springframework.ws.context.MessageContext;
34  import org.springframework.ws.server.endpoint.annotation.RequestPayload;
35  import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
36  import org.springframework.ws.soap.axiom.AxiomSoapMessage;
37  import org.springframework.ws.soap.axiom.AxiomSoapMessageFactory;
38  import org.springframework.xml.transform.StringResult;
39  
40  import org.junit.Before;
41  import org.junit.Test;
42  import org.xml.sax.SAXException;
43  
44  import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
45  import static org.junit.Assert.assertEquals;
46  import static org.junit.Assert.assertTrue;
47  
48  public class XmlRootElementPayloadMethodProcessorTest {
49  
50      private XmlRootElementPayloadMethodProcessor processor;
51  
52      private MethodParameter rootElementParameter;
53  
54      private MethodParameter typeParameter;
55  
56      private MethodParameter rootElementReturnType;
57  
58      @Before
59      public void setUp() throws Exception {
60          processor = new XmlRootElementPayloadMethodProcessor();
61          rootElementParameter = new MethodParameter(getClass().getMethod("rootElement", MyRootElement.class), 0);
62          typeParameter = new MethodParameter(getClass().getMethod("type", MyType.class), 0);
63          rootElementReturnType = new MethodParameter(getClass().getMethod("rootElement", MyRootElement.class), -1);
64      }
65  
66      @Test
67      public void supportsParameter() {
68          assertTrue("processor does not support @XmlRootElement parameter",
69                  processor.supportsParameter(rootElementParameter));
70          assertTrue("processor does not support @XmlType parameter", processor.supportsParameter(typeParameter));
71      }
72  
73      @Test
74      public void supportsReturnType() {
75          assertTrue("processor does not support @XmlRootElement return type",
76                  processor.supportsReturnType(rootElementReturnType));
77      }
78  
79      @Test
80      public void resolveArgumentRootElement() throws JAXBException {
81          WebServiceMessage request = new MockWebServiceMessage("<root xmlns='http://springframework.org'><string>Foo</string></root>");
82          MessageContext messageContext = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
83  
84          Object result = processor.resolveArgument(messageContext, rootElementParameter);
85          assertTrue("result not a MyRootElement", result instanceof MyRootElement);
86          MyRootElement rootElement = (MyRootElement) result;
87          assertEquals("invalid result", "Foo", rootElement.getString());
88      }
89  
90      @Test
91      public void resolveArgumentType() throws JAXBException {
92          WebServiceMessage request = new MockWebServiceMessage("<type xmlns='http://springframework.org'><string>Foo</string></type>");
93          MessageContext messageContext = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
94  
95          Object result = processor.resolveArgument(messageContext, typeParameter);
96          assertTrue("result not a MyType", result instanceof MyType);
97          MyType type = (MyType) result;
98          assertEquals("invalid result", "Foo", type.getString());
99      }
100 
101     @Test
102     public void handleReturnValue() throws JAXBException, IOException, SAXException {
103         MessageContext messageContext = new DefaultMessageContext(new MockWebServiceMessageFactory());
104 
105         MyRootElement rootElement = new MyRootElement();
106         rootElement.setString("Foo");
107         processor.handleReturnValue(messageContext, rootElementReturnType, rootElement);
108         assertTrue("context has no response", messageContext.hasResponse());
109         MockWebServiceMessage response = (MockWebServiceMessage) messageContext.getResponse();
110         assertXMLEqual("<root xmlns='http://springframework.org'><string>Foo</string></root>", response.getPayloadAsString());
111     }
112 
113     @Test
114     public void handleReturnValueAxiom() throws Exception {
115         AxiomSoapMessageFactory messageFactory = new AxiomSoapMessageFactory();
116         MessageContext messageContext = new DefaultMessageContext(messageFactory);
117 
118         MyRootElement rootElement = new MyRootElement();
119         rootElement.setString("Foo");
120 
121         processor.handleReturnValue(messageContext, rootElementReturnType, rootElement);
122         assertTrue("context has no response", messageContext.hasResponse());
123         AxiomSoapMessage response = (AxiomSoapMessage) messageContext.getResponse();
124 
125         Transformer transformer = TransformerFactory.newInstance().newTransformer();
126         StringResult payloadResult = new StringResult();
127         transformer.transform(response.getPayloadSource(), payloadResult);
128 
129         assertXMLEqual("<root xmlns='http://springframework.org'><string>Foo</string></root>",
130                 payloadResult.toString());
131 
132         ByteArrayOutputStream bos = new ByteArrayOutputStream();
133         response.writeTo(bos);
134         String messageResult = bos.toString("UTF-8");
135         
136         assertXMLEqual("<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'><soapenv:Body>" +
137                 "<root xmlns='http://springframework.org'><string>Foo</string></root>" +
138                 "</soapenv:Body></soapenv:Envelope>", messageResult);
139 
140     }
141 
142     @Test
143     public void handleReturnValueAxiomNoPayloadCaching() throws Exception {
144         AxiomSoapMessageFactory messageFactory = new AxiomSoapMessageFactory();
145         messageFactory.setPayloadCaching(false);
146         MessageContext messageContext = new DefaultMessageContext(messageFactory);
147 
148         MyRootElement rootElement = new MyRootElement();
149         rootElement.setString("Foo");
150 
151         processor.handleReturnValue(messageContext, rootElementReturnType, rootElement);
152         assertTrue("context has no response", messageContext.hasResponse());
153         AxiomSoapMessage response = (AxiomSoapMessage) messageContext.getResponse();
154 
155         ByteArrayOutputStream bos = new ByteArrayOutputStream();
156         response.writeTo(bos);
157         String messageResult = bos.toString("UTF-8");
158 
159         assertXMLEqual("<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'><soapenv:Body>" +
160                 "<root xmlns='http://springframework.org'><string>Foo</string></root>" +
161                 "</soapenv:Body></soapenv:Envelope>", messageResult);
162 
163     }
164 
165     @ResponsePayload
166     public MyRootElement rootElement(@RequestPayload MyRootElement rootElement) {
167         return rootElement;
168     }
169 
170     public void type(@RequestPayload MyType type) {
171     }
172 
173     @XmlRootElement(name = "root", namespace = "http://springframework.org")
174     public static class MyRootElement {
175 
176         private String string;
177 
178         @XmlElement(name = "string", namespace = "http://springframework.org")
179         public String getString() {
180             return string;
181         }
182 
183         public void setString(String string) {
184             this.string = string;
185         }
186     }
187 
188     @XmlType(name = "root", namespace = "http://springframework.org")
189     public static class MyType {
190 
191         private String string;
192 
193         @XmlElement(name = "string", namespace = "http://springframework.org")
194         public String getString() {
195             return string;
196         }
197 
198         public void setString(String string) {
199             this.string = string;
200         }
201     }
202 
203 
204 }