diff --git a/core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/MarshallingPayloadMethodProcessor.java b/core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/MarshallingPayloadMethodProcessor.java new file mode 100644 index 00000000..8c7d92d7 --- /dev/null +++ b/core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/MarshallingPayloadMethodProcessor.java @@ -0,0 +1,120 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ws.server.endpoint.adapter.method; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.core.MethodParameter; +import org.springframework.oxm.GenericMarshaller; +import org.springframework.oxm.GenericUnmarshaller; +import org.springframework.oxm.Marshaller; +import org.springframework.oxm.Unmarshaller; +import org.springframework.util.Assert; +import org.springframework.ws.WebServiceMessage; +import org.springframework.ws.context.MessageContext; +import org.springframework.ws.support.MarshallingUtils; + +/** + * Implementation of {@link MethodArgumentResolver} and {@link MethodReturnValueHandler} that uses {@link Marshaller} + * and {@link Unmarshaller} to support marshalled objects. + * + * @author Arjen Poutsma + * @since 2.0 + */ +public class MarshallingPayloadMethodProcessor extends AbstractPayloadMethodProcessor implements InitializingBean { + + private Marshaller marshaller; + + private Unmarshaller unmarshaller; + + public MarshallingPayloadMethodProcessor() { + } + + public MarshallingPayloadMethodProcessor(Marshaller marshaller) { + Assert.notNull(marshaller, "marshaller must not be null"); + Assert.isInstanceOf(Unmarshaller.class, marshaller); + setMarshaller(marshaller); + setUnmarshaller((Unmarshaller) marshaller); + } + + public MarshallingPayloadMethodProcessor(Marshaller marshaller, Unmarshaller unmarshaller) { + Assert.notNull(marshaller, "marshaller must not be null"); + Assert.notNull(unmarshaller, "unmarshaller must not be null"); + setMarshaller(marshaller); + setUnmarshaller(unmarshaller); + } + + public Marshaller getMarshaller() { + return marshaller; + } + + public void setMarshaller(Marshaller marshaller) { + this.marshaller = marshaller; + } + + public Unmarshaller getUnmarshaller() { + return unmarshaller; + } + + public void setUnmarshaller(Unmarshaller unmarshaller) { + this.unmarshaller = unmarshaller; + } + + public void afterPropertiesSet() throws Exception { + Assert.notNull(marshaller, "marshaller is required"); + Assert.notNull(unmarshaller, "unmarshaller is required"); + } + + @Override + protected boolean supportsRequestPayloadParameter(MethodParameter parameter) { + if (unmarshaller instanceof GenericUnmarshaller) { + return ((GenericUnmarshaller) unmarshaller).supports(parameter.getGenericParameterType()); + } + else { + return unmarshaller.supports(parameter.getParameterType()); + } + } + + public Object resolveArgument(MessageContext messageContext, MethodParameter parameter) throws Exception { + WebServiceMessage request = messageContext.getRequest(); + Object requestObject = MarshallingUtils.unmarshal(getUnmarshaller(), request); + if (logger.isDebugEnabled()) { + logger.debug("Unmarshalled payload request to [" + requestObject + "]"); + } + return requestObject; + } + + @Override + protected boolean supportsResponsePayloadReturnType(MethodParameter returnType) { + if (marshaller instanceof GenericMarshaller) { + GenericMarshaller genericMarshaller = (GenericMarshaller) marshaller; + return genericMarshaller.supports(returnType.getGenericParameterType()); + } + else { + return marshaller.supports(returnType.getParameterType()); + } + } + + public void handleReturnValue(MessageContext messageContext, MethodParameter returnType, Object returnValue) + throws Exception { + if (logger.isDebugEnabled()) { + logger.debug("Marshalling [" + returnValue + "] to response payload"); + } + WebServiceMessage response = messageContext.getResponse(); + MarshallingUtils.marshal(getMarshaller(), returnValue, response); + } + +} diff --git a/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/AbstractMethodArgumentResolverTest.java b/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/AbstractMethodArgumentResolverTestCase.java similarity index 96% rename from core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/AbstractMethodArgumentResolverTest.java rename to core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/AbstractMethodArgumentResolverTestCase.java index dc5cca3c..51e64965 100644 --- a/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/AbstractMethodArgumentResolverTest.java +++ b/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/AbstractMethodArgumentResolverTestCase.java @@ -32,8 +32,7 @@ import org.springframework.xml.transform.TransformerObjectSupport; import org.apache.axiom.om.OMAbstractFactory; import org.apache.axiom.soap.SOAPFactory; -/** @author Arjen Poutsma */ -public class AbstractMethodArgumentResolverTest extends TransformerObjectSupport { +public class AbstractMethodArgumentResolverTestCase extends TransformerObjectSupport { protected static final String NAMESPACE_URI = "http://springframework.org/ws"; diff --git a/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/AbstractPayloadMethodProcessorTestCase.java b/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/AbstractPayloadMethodProcessorTestCase.java index 6b72fe57..b097a891 100644 --- a/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/AbstractPayloadMethodProcessorTestCase.java +++ b/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/AbstractPayloadMethodProcessorTestCase.java @@ -29,7 +29,7 @@ import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -public abstract class AbstractPayloadMethodProcessorTestCase extends AbstractMethodArgumentResolverTest { +public abstract class AbstractPayloadMethodProcessorTestCase extends AbstractMethodArgumentResolverTestCase { private AbstractPayloadSourceMethodProcessor processor; diff --git a/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/MarshallingPayloadMethodProcessorTest.java b/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/MarshallingPayloadMethodProcessorTest.java new file mode 100644 index 00000000..6ddac3a6 --- /dev/null +++ b/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/MarshallingPayloadMethodProcessorTest.java @@ -0,0 +1,138 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ws.server.endpoint.adapter.method; + +import java.lang.reflect.Type; +import javax.xml.transform.Result; +import javax.xml.transform.Source; + +import org.springframework.core.MethodParameter; +import org.springframework.oxm.GenericMarshaller; +import org.springframework.oxm.GenericUnmarshaller; +import org.springframework.ws.context.MessageContext; +import org.springframework.ws.server.endpoint.annotation.RequestPayload; +import org.springframework.ws.server.endpoint.annotation.ResponsePayload; + +import org.junit.Before; +import org.junit.Test; + +import static org.easymock.EasyMock.*; +import static org.junit.Assert.*; + +public class MarshallingPayloadMethodProcessorTest extends AbstractMethodArgumentResolverTestCase { + + private MarshallingPayloadMethodProcessor processor; + + private GenericMarshaller marshaller; + + private GenericUnmarshaller unmarshaller; + + private MethodParameter supportedParameter; + + private MethodParameter supportedReturnType; + + @Before + public void setUp() throws Exception { + marshaller = createMock("marshaller", GenericMarshaller.class); + unmarshaller = createMock("unmarshaller", GenericUnmarshaller.class); + processor = new MarshallingPayloadMethodProcessor(marshaller, unmarshaller); + supportedParameter = new MethodParameter(getClass().getMethod("method", MyObject.class), 0); + supportedReturnType = new MethodParameter(getClass().getMethod("method", MyObject.class), -1); + } + + @Test + public void supportsParameterSupported() { + expect(unmarshaller.supports(isA(Type.class))).andReturn(true); + + replay(marshaller, unmarshaller); + + assertTrue("processor does not support supported parameter", processor.supportsParameter(supportedParameter)); + + verify(marshaller, unmarshaller); + } + + @Test + public void supportsParameterUnsupported() { + expect(unmarshaller.supports(isA(Type.class))).andReturn(false); + + replay(marshaller, unmarshaller); + + assertFalse("processor supports unsupported parameter", processor.supportsParameter(supportedParameter)); + + verify(marshaller, unmarshaller); + } + + @Test + public void supportsReturnTypeSupported() { + expect(marshaller.supports(isA(Type.class))).andReturn(true); + + replay(marshaller, unmarshaller); + + assertTrue("processor does not support supported return type", processor.supportsReturnType(supportedReturnType)); + + verify(marshaller, unmarshaller); + } + + @Test + public void supportsReturnTypeUnsupported() { + expect(marshaller.supports(isA(Type.class))).andReturn(false); + + replay(marshaller, unmarshaller); + + assertFalse("processor supports unsupported parameter", processor.supportsReturnType(supportedReturnType)); + + verify(marshaller, unmarshaller); + } + + @Test + public void resolveArgument() throws Exception { + MyObject expected = new MyObject(); + + expect(unmarshaller.unmarshal(isA(Source.class))).andReturn(expected); + + replay(marshaller, unmarshaller); + MessageContext messageContext = createMockMessageContext(); + + Object result = processor.resolveArgument(messageContext, supportedParameter); + assertEquals("Invalid return argument", expected, result); + + verify(marshaller, unmarshaller); + } + + @Test + public void handleReturnValue() throws Exception { + MyObject returnValue = new MyObject(); + + marshaller.marshal(eq(returnValue), isA(Result.class)); + + replay(marshaller, unmarshaller); + MessageContext messageContext = createMockMessageContext(); + + processor.handleReturnValue(messageContext, supportedReturnType, returnValue); + + verify(marshaller, unmarshaller); + } + + @ResponsePayload + public MyObject method(@RequestPayload MyObject object) { + return object; + } + + public static class MyObject { + + } +} diff --git a/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/StaxPayloadMethodArgumentResolverTest.java b/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/StaxPayloadMethodArgumentResolverTest.java index 044b1f38..ff3cfa7f 100644 --- a/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/StaxPayloadMethodArgumentResolverTest.java +++ b/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/StaxPayloadMethodArgumentResolverTest.java @@ -34,7 +34,7 @@ import static org.junit.Assert.*; /** @author Arjen Poutsma */ @SuppressWarnings("Since15") -public class StaxPayloadMethodArgumentResolverTest extends AbstractMethodArgumentResolverTest { +public class StaxPayloadMethodArgumentResolverTest extends AbstractMethodArgumentResolverTestCase { private StaxPayloadMethodArgumentResolver resolver; diff --git a/core/src/test/java/org/springframework/ws/soap/server/endpoint/adapter/method/SoapMethodArgumentResolverTest.java b/core/src/test/java/org/springframework/ws/soap/server/endpoint/adapter/method/SoapMethodArgumentResolverTest.java index f0b9ff33..ee3d1223 100644 --- a/core/src/test/java/org/springframework/ws/soap/server/endpoint/adapter/method/SoapMethodArgumentResolverTest.java +++ b/core/src/test/java/org/springframework/ws/soap/server/endpoint/adapter/method/SoapMethodArgumentResolverTest.java @@ -18,7 +18,7 @@ package org.springframework.ws.soap.server.endpoint.adapter.method; import org.springframework.core.MethodParameter; import org.springframework.ws.context.MessageContext; -import org.springframework.ws.server.endpoint.adapter.method.AbstractMethodArgumentResolverTest; +import org.springframework.ws.server.endpoint.adapter.method.AbstractMethodArgumentResolverTestCase; import org.springframework.ws.soap.SoapBody; import org.springframework.ws.soap.SoapEnvelope; import org.springframework.ws.soap.SoapHeader; @@ -31,7 +31,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; /** @author Arjen Poutsma */ -public class SoapMethodArgumentResolverTest extends AbstractMethodArgumentResolverTest { +public class SoapMethodArgumentResolverTest extends AbstractMethodArgumentResolverTestCase { private SoapMethodArgumentResolver resolver;