diff --git a/changelog.txt b/changelog.txt index 50faca03..1eb80049 100644 --- a/changelog.txt +++ b/changelog.txt @@ -22,6 +22,9 @@ Package org.springframework.ws.client.core could be closed before returned. Package org.springframework.ws.server.endpoint +* added MarshallingMethodEndpointAdapter + +Package org.springframework.ws.server.endpoint.mapping * added XPathPayloadEndpointMapping (#SWS-85). Package org.springframework.ws.soap.saaj diff --git a/sandbox/src/main/java/org/springframework/ws/server/endpoint/MarshallingMethodEndpointAdapter.java b/sandbox/src/main/java/org/springframework/ws/server/endpoint/MarshallingMethodEndpointAdapter.java new file mode 100644 index 00000000..84fb6446 --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/server/endpoint/MarshallingMethodEndpointAdapter.java @@ -0,0 +1,96 @@ +/* + * Copyright 2007 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; + +import java.lang.reflect.Method; + +import org.springframework.beans.factory.InitializingBean; +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.server.EndpointMapping; + +/** + * Adapter that supports endpoint methods that use marshalling. Supports methods with the following signature: + *
+ * void handleMyMessage(MyUnmarshalledType request); + *+ * or + *
+ * MyMarshalledType handleMyMessage(MyUnmarshalledType request); + *+ * I.e. methods that take a single parameter that {@link Unmarshaller#supports(Class) is supported} by the {@link + * Unmarshaller}, and return either
void or a type {@link Marshaller#supports(Class) supported} by the
+ * {@link Marshaller}. The method can have any name, as long as it is mapped by an {@link EndpointMapping}.
+ *
+ * This endpoint needs a Marshaller and Unmarshaller, both of which can be set using
+ * properties.
+ *
+ * @author Arjen Poutsma
+ * @see #setMarshaller(org.springframework.oxm.Marshaller)
+ * @see #setUnmarshaller(org.springframework.oxm.Unmarshaller)
+ */
+public class MarshallingMethodEndpointAdapter extends AbstractMethodEndpointAdapter implements InitializingBean {
+
+ private Marshaller marshaller;
+
+ private Unmarshaller unmarshaller;
+
+ public void setMarshaller(Marshaller marshaller) {
+ this.marshaller = marshaller;
+ }
+
+ 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");
+ }
+
+ /**
+ * Supports a method with a single, unmarshallable parameter, and that return void or a marshallable
+ * type.
+ *
+ * @see Marshaller#supports(Class)
+ * @see Unmarshaller#supports(Class)
+ */
+ protected boolean supportsInternal(MethodEndpoint methodEndpoint) {
+ Method method = methodEndpoint.getMethod();
+ return (Void.TYPE.isAssignableFrom(method.getReturnType()) || marshaller.supports(method.getReturnType())) &&
+ method.getParameterTypes().length == 1 && unmarshaller.supports(method.getParameterTypes()[0]);
+ }
+
+ protected void invokeInternal(MessageContext messageContext, MethodEndpoint methodEndpoint) throws Exception {
+ WebServiceMessage request = messageContext.getRequest();
+ Object requestObject = unmarshaller.unmarshal(request.getPayloadSource());
+ if (logger.isDebugEnabled()) {
+ logger.debug("Unmarshalled payload request to [" + requestObject + "]");
+ }
+ Object responseObject = methodEndpoint.invoke(new Object[]{requestObject});
+ if (responseObject != null) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Marshalling [" + responseObject + "] to response payload");
+ }
+ WebServiceMessage response = messageContext.getResponse();
+ marshaller.marshal(responseObject, response.getPayloadResult());
+ }
+ }
+}
diff --git a/sandbox/src/test/java/org/springframework/ws/server/endpoint/MarshallingMethodEndpointAdapterTest.java b/sandbox/src/test/java/org/springframework/ws/server/endpoint/MarshallingMethodEndpointAdapterTest.java
new file mode 100644
index 00000000..abf55ad7
--- /dev/null
+++ b/sandbox/src/test/java/org/springframework/ws/server/endpoint/MarshallingMethodEndpointAdapterTest.java
@@ -0,0 +1,149 @@
+package org.springframework.ws.server.endpoint;
+
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+import org.springframework.oxm.Marshaller;
+import org.springframework.oxm.Unmarshaller;
+import org.springframework.ws.MockWebServiceMessageFactory;
+import org.springframework.ws.context.DefaultMessageContext;
+import org.springframework.ws.context.MessageContext;
+
+public class MarshallingMethodEndpointAdapterTest extends TestCase {
+
+ private MarshallingMethodEndpointAdapter adapter;
+
+ private boolean noResponseInvoked;
+
+ private MockControl marshallerControl;
+
+ private Marshaller marshallerMock;
+
+ private MockControl unmarshallerControl;
+
+ private Unmarshaller unmarshallerMock;
+
+ private MessageContext messageContext;
+
+ private boolean responseInvoked;
+
+ protected void setUp() throws Exception {
+ adapter = new MarshallingMethodEndpointAdapter();
+ marshallerControl = MockControl.createControl(Marshaller.class);
+ marshallerMock = (Marshaller) marshallerControl.getMock();
+ adapter.setMarshaller(marshallerMock);
+ unmarshallerControl = MockControl.createControl(Unmarshaller.class);
+ unmarshallerMock = (Unmarshaller) unmarshallerControl.getMock();
+ adapter.setUnmarshaller(unmarshallerMock);
+ adapter.afterPropertiesSet();
+ messageContext = new DefaultMessageContext(new MockWebServiceMessageFactory());
+ }
+
+ public void testNoResponse() throws Exception {
+ Method noResponse = getClass().getMethod("noResponse", new Class[]{MyType.class});
+ MethodEndpoint methodEndpoint = new MethodEndpoint(this, noResponse);
+ unmarshallerMock.unmarshal(messageContext.getRequest().getPayloadSource());
+ unmarshallerControl.setMatcher(MockControl.ALWAYS_MATCHER);
+ unmarshallerControl.setReturnValue(new MyType());
+ marshallerControl.replay();
+ unmarshallerControl.replay();
+ assertFalse("Method invoked", noResponseInvoked);
+ adapter.invoke(messageContext, methodEndpoint);
+ assertTrue("Method not invoked", noResponseInvoked);
+ marshallerControl.verify();
+ unmarshallerControl.verify();
+ }
+
+ public void testResponse() throws Exception {
+ Method response = getClass().getMethod("response", new Class[]{MyType.class});
+ MethodEndpoint methodEndpoint = new MethodEndpoint(this, response);
+ unmarshallerMock.unmarshal(messageContext.getRequest().getPayloadSource());
+ unmarshallerControl.setMatcher(MockControl.ALWAYS_MATCHER);
+ unmarshallerControl.setReturnValue(new MyType());
+ marshallerMock.marshal(new MyType(), messageContext.getResponse().getPayloadResult());
+ marshallerControl.setMatcher(MockControl.ALWAYS_MATCHER);
+ marshallerControl.replay();
+ unmarshallerControl.replay();
+ assertFalse("Method invoked", responseInvoked);
+ adapter.invoke(messageContext, methodEndpoint);
+ assertTrue("Method not invoked", responseInvoked);
+ marshallerControl.verify();
+ unmarshallerControl.verify();
+
+ }
+
+ public void testSupportedNoResponse() throws NoSuchMethodException {
+ Method noResponse = getClass().getMethod("noResponse", new Class[]{MyType.class});
+ MethodEndpoint methodEndpoint = new MethodEndpoint(this, noResponse);
+ unmarshallerControl.expectAndReturn(unmarshallerMock.supports(MyType.class), true);
+ marshallerControl.replay();
+ unmarshallerControl.replay();
+ assertTrue("Method unsupported", adapter.supportsInternal(methodEndpoint));
+ marshallerControl.verify();
+ unmarshallerControl.verify();
+ }
+
+ public void testSupportedResponse() throws NoSuchMethodException {
+ Method response = getClass().getMethod("response", new Class[]{MyType.class});
+ MethodEndpoint methodEndpoint = new MethodEndpoint(this, response);
+ unmarshallerControl.expectAndReturn(unmarshallerMock.supports(MyType.class), true);
+ marshallerControl.expectAndReturn(marshallerMock.supports(MyType.class), true);
+ marshallerControl.replay();
+ unmarshallerControl.replay();
+ assertTrue("Method unsupported", adapter.supportsInternal(methodEndpoint));
+ marshallerControl.verify();
+ unmarshallerControl.verify();
+ }
+
+ public void testUnsupportedMethodMultipleParams() throws NoSuchMethodException {
+ Method unsupported = getClass().getMethod("unsupportedMultipleParams", new Class[]{String.class, String.class});
+ marshallerControl.replay();
+ unmarshallerControl.replay();
+ assertFalse("Method supported", adapter.supportsInternal(new MethodEndpoint(this, unsupported)));
+ marshallerControl.verify();
+ unmarshallerControl.verify();
+ }
+
+ public void testUnsupportedMethodWrongParam() throws NoSuchMethodException {
+ Method unsupported = getClass().getMethod("unsupportedWrongParam", new Class[]{String.class});
+ unmarshallerControl.expectAndReturn(unmarshallerMock.supports(String.class), false);
+ marshallerControl.expectAndReturn(marshallerMock.supports(String.class), true);
+ marshallerControl.replay();
+ unmarshallerControl.replay();
+ assertFalse("Method supported", adapter.supportsInternal(new MethodEndpoint(this, unsupported)));
+ marshallerControl.verify();
+ unmarshallerControl.verify();
+ }
+
+ public void testUnsupportedMethodWrongReturnType() throws NoSuchMethodException {
+ Method unsupported = getClass().getMethod("unsupportedWrongParam", new Class[]{String.class});
+ marshallerControl.expectAndReturn(marshallerMock.supports(String.class), false);
+ marshallerControl.replay();
+ unmarshallerControl.replay();
+ assertFalse("Method supported", adapter.supportsInternal(new MethodEndpoint(this, unsupported)));
+ marshallerControl.verify();
+ unmarshallerControl.verify();
+ }
+
+ public void noResponse(MyType type) {
+ noResponseInvoked = true;
+
+ }
+
+ public MyType response(MyType type) {
+ responseInvoked = true;
+ return new MyType();
+ }
+
+ public void unsupportedMultipleParams(String s1, String s2) {
+ }
+
+ public String unsupportedWrongParam(String s) {
+ return s;
+ }
+
+ public static class MyType {
+
+ }
+}
\ No newline at end of file