diff --git a/core/src/main/java/org/springframework/ws/transport/AbstractReceiverConnection.java b/core/src/main/java/org/springframework/ws/transport/AbstractReceiverConnection.java index b8dac276..7c4a07f0 100644 --- a/core/src/main/java/org/springframework/ws/transport/AbstractReceiverConnection.java +++ b/core/src/main/java/org/springframework/ws/transport/AbstractReceiverConnection.java @@ -101,10 +101,6 @@ public abstract class AbstractReceiverConnection extends AbstractWebServiceConne return getResponseOutputStream(); } - public void close() throws IOException { - super.close(); - } - } diff --git a/core/src/main/java/org/springframework/ws/transport/AbstractWebServiceConnection.java b/core/src/main/java/org/springframework/ws/transport/AbstractWebServiceConnection.java index c67ee052..e17079d7 100644 --- a/core/src/main/java/org/springframework/ws/transport/AbstractWebServiceConnection.java +++ b/core/src/main/java/org/springframework/ws/transport/AbstractWebServiceConnection.java @@ -29,6 +29,7 @@ import org.springframework.ws.WebServiceMessageFactory; public abstract class AbstractWebServiceConnection implements WebServiceConnection { public final void send(WebServiceMessage message) throws IOException { + onSendBeforeWrite(message); TransportOutputStream tos = createTransportOutputStream(); try { message.writeTo(tos); @@ -37,10 +38,11 @@ public abstract class AbstractWebServiceConnection implements WebServiceConnecti finally { tos.close(); } - onSend(message); + onSendAfterWrite(message); } public final WebServiceMessage receive(WebServiceMessageFactory messageFactory) throws IOException { + onReceiveBeforeRead(); TransportInputStream tis = createTransportInputStream(); if (tis == null) { return null; @@ -52,7 +54,7 @@ public abstract class AbstractWebServiceConnection implements WebServiceConnecti finally { tis.close(); } - onReceive(message); + onReceiveAfterRead(message); return message; } @@ -66,7 +68,7 @@ public abstract class AbstractWebServiceConnection implements WebServiceConnecti protected abstract TransportOutputStream createTransportOutputStream() throws IOException; /** - * Called when the given message has been written to the TransportOutputStream. Called from {@link + * Called before the given message has been written to the TransportOutputStream. Called from {@link * #send(WebServiceMessage)}. *

* Default implementation does nothing. @@ -74,8 +76,19 @@ public abstract class AbstractWebServiceConnection implements WebServiceConnecti * @param message the message * @throws IOException when an I/O exception occurs */ - protected void onSend(WebServiceMessage message) throws IOException { + protected void onSendBeforeWrite(WebServiceMessage message) throws IOException { + } + /** + * Called after the given message has been written to the TransportOutputStream. Called from {@link + * #send(WebServiceMessage)}. + *

+ * Default implementation does nothing. + * + * @param message the message + * @throws IOException when an I/O exception occurs + */ + protected void onSendAfterWrite(WebServiceMessage message) throws IOException { } /** @@ -87,7 +100,18 @@ public abstract class AbstractWebServiceConnection implements WebServiceConnecti protected abstract TransportInputStream createTransportInputStream() throws IOException; /** - * Called when the given message has been written to the TransportOutputStream. Called from {@link + * Called before a message has been read from the TransportInputStream. Called from {@link + * #receive(WebServiceMessageFactory)}. + *

+ * Default implementation does nothing. + * + * @throws IOException when an I/O exception occurs + */ + protected void onReceiveBeforeRead() throws IOException { + } + + /** + * Called when the given message has been read from the TransportInputStream. Called from {@link * #receive(WebServiceMessageFactory)}. *

* Default implementation does nothing. @@ -95,8 +119,7 @@ public abstract class AbstractWebServiceConnection implements WebServiceConnecti * @param message the message * @throws IOException when an I/O exception occurs */ - protected void onReceive(WebServiceMessage message) throws IOException { - + protected void onReceiveAfterRead(WebServiceMessage message) throws IOException { } } diff --git a/core/src/main/java/org/springframework/ws/transport/http/CommonsHttpConnection.java b/core/src/main/java/org/springframework/ws/transport/http/CommonsHttpConnection.java index 50e1ffa7..a2fe6687 100644 --- a/core/src/main/java/org/springframework/ws/transport/http/CommonsHttpConnection.java +++ b/core/src/main/java/org/springframework/ws/transport/http/CommonsHttpConnection.java @@ -44,7 +44,7 @@ public class CommonsHttpConnection extends AbstractHttpSenderConnection { private final PostMethod postMethod; - private ByteArrayOutputStream bufferedOutput = new ByteArrayOutputStream(); + private ByteArrayOutputStream bufferedOutput; public CommonsHttpConnection(HttpClient httpClient, PostMethod postMethod) { Assert.notNull(httpClient, "httpClient must not be null"); @@ -61,6 +61,14 @@ public class CommonsHttpConnection extends AbstractHttpSenderConnection { postMethod.releaseConnection(); } + /* + * Sending request + */ + + protected void onSendBeforeWrite(WebServiceMessage message) throws IOException { + bufferedOutput = new ByteArrayOutputStream(); + } + protected void addRequestHeader(String name, String value) throws IOException { postMethod.addRequestHeader(name, value); } @@ -69,12 +77,16 @@ public class CommonsHttpConnection extends AbstractHttpSenderConnection { return bufferedOutput; } - protected void onSend(WebServiceMessage message) throws IOException { + protected void onSendAfterWrite(WebServiceMessage message) throws IOException { postMethod.setRequestEntity(new ByteArrayRequestEntity(bufferedOutput.toByteArray())); bufferedOutput = null; httpClient.executeMethod(postMethod); } + /* + * Receiving response + */ + protected int getResponseCode() throws IOException { return postMethod.getStatusCode(); } diff --git a/core/src/main/java/org/springframework/ws/transport/http/HttpServletConnection.java b/core/src/main/java/org/springframework/ws/transport/http/HttpServletConnection.java index a223a65f..1f0dfeeb 100644 --- a/core/src/main/java/org/springframework/ws/transport/http/HttpServletConnection.java +++ b/core/src/main/java/org/springframework/ws/transport/http/HttpServletConnection.java @@ -53,12 +53,6 @@ public class HttpServletConnection extends AbstractReceiverConnection implements this.httpServletResponse = httpServletResponse; } - public void close() throws IOException { - if (!sentResponse && endpointFound) { - httpServletResponse.setStatus(HttpServletResponse.SC_ACCEPTED); - } - } - /** Returns the HttpServletRequest for this connection. */ public HttpServletRequest getHttpServletRequest() { return httpServletRequest; @@ -74,6 +68,16 @@ public class HttpServletConnection extends AbstractReceiverConnection implements httpServletResponse.setStatus(HttpServletResponse.SC_NOT_FOUND); } + public void close() throws IOException { + if (!sentResponse && endpointFound) { + httpServletResponse.setStatus(HttpServletResponse.SC_ACCEPTED); + } + } + + /* + * Receiving request + */ + protected Iterator getRequestHeaderNames() throws IOException { return new EnumerationIterator(httpServletRequest.getHeaderNames()); } @@ -86,6 +90,10 @@ public class HttpServletConnection extends AbstractReceiverConnection implements return httpServletRequest.getInputStream(); } + /* + * Sending response + */ + protected void addResponseHeader(String name, String value) throws IOException { httpServletResponse.addHeader(name, value); } @@ -94,7 +102,7 @@ public class HttpServletConnection extends AbstractReceiverConnection implements return httpServletResponse.getOutputStream(); } - protected void onSend(WebServiceMessage message) throws IOException { + protected void onSendBeforeWrite(WebServiceMessage message) throws IOException { sentResponse = true; if (!message.hasFault()) { httpServletResponse.setStatus(HttpServletResponse.SC_OK); diff --git a/core/src/main/java/org/springframework/ws/transport/http/HttpUrlConnection.java b/core/src/main/java/org/springframework/ws/transport/http/HttpUrlConnection.java index ae26bc19..02d3bd77 100644 --- a/core/src/main/java/org/springframework/ws/transport/http/HttpUrlConnection.java +++ b/core/src/main/java/org/springframework/ws/transport/http/HttpUrlConnection.java @@ -58,6 +58,10 @@ public class HttpUrlConnection extends AbstractHttpSenderConnection { connection.disconnect(); } + /* + * Sending request + */ + protected void addRequestHeader(String name, String value) throws IOException { connection.addRequestProperty(name, value); } @@ -66,10 +70,14 @@ public class HttpUrlConnection extends AbstractHttpSenderConnection { return connection.getOutputStream(); } - protected void onSend(WebServiceMessage message) throws IOException { + protected void onSendAfterWrite(WebServiceMessage message) throws IOException { connection.connect(); } + /* + * Receiving response + */ + protected long getResponseContentLength() throws IOException { return connection.getContentLength(); } diff --git a/core/src/test/java/org/springframework/ws/transport/http/FaultEndpoint.java b/core/src/test/java/org/springframework/ws/transport/http/FaultEndpoint.java new file mode 100644 index 00000000..69cfb2ee --- /dev/null +++ b/core/src/test/java/org/springframework/ws/transport/http/FaultEndpoint.java @@ -0,0 +1,31 @@ +/* + * 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.transport.http; + +import java.util.Locale; + +import org.springframework.ws.context.MessageContext; +import org.springframework.ws.server.endpoint.MessageEndpoint; +import org.springframework.ws.soap.SoapMessage; + +public class FaultEndpoint implements MessageEndpoint { + + public void invoke(MessageContext messageContext) throws Exception { + SoapMessage response = (SoapMessage) messageContext.getResponse(); + response.getSoapBody().addServerOrReceiverFault("Something went wrong", Locale.ENGLISH); + } +} diff --git a/core/src/test/java/org/springframework/ws/transport/http/MessageDispatcherServletIntegrationTest.java b/core/src/test/java/org/springframework/ws/transport/http/MessageDispatcherServletIntegrationTest.java new file mode 100644 index 00000000..876f82f0 --- /dev/null +++ b/core/src/test/java/org/springframework/ws/transport/http/MessageDispatcherServletIntegrationTest.java @@ -0,0 +1,104 @@ +/* + * 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.transport.http; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.methods.InputStreamRequestEntity; +import org.apache.commons.httpclient.methods.PostMethod; +import org.mortbay.jetty.Server; +import org.mortbay.jetty.servlet.Context; +import org.mortbay.jetty.servlet.ServletHolder; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +public class MessageDispatcherServletIntegrationTest extends TestCase { + + private Server jettyServer; + + private HttpClient client; + + private static final String SOAP_ACTION = "SOAPAction"; + + private static final String CONTENT_TYPE = "Content-Type"; + + protected final void setUp() throws Exception { + jettyServer = new Server(8888); + Context jettyContext = new Context(jettyServer, "/"); + File dir = new File(getClass().getResource(".").toURI()); + jettyContext.setResourceBase(dir.getAbsolutePath()); + ServletHolder servletHolder = new ServletHolder(new MessageDispatcherServlet()); + servletHolder.setName("spring-ws"); + jettyContext.addServlet(servletHolder, "/*"); + jettyServer.start(); + client = new HttpClient(); + } + + protected void tearDown() throws Exception { + jettyServer.stop(); + } + + public void testNoResponse() throws IOException { + PostMethod postMethod = new PostMethod("http://localhost:8888/service"); + postMethod.addRequestHeader(CONTENT_TYPE, "text/xml"); + postMethod.addRequestHeader(SOAP_ACTION, "http://springframework.org/spring-ws/NoResponse"); + Resource soapRequest = new ClassPathResource("soapRequest.xml", MessageDispatcherServletIntegrationTest.class); + postMethod.setRequestEntity(new InputStreamRequestEntity(soapRequest.getInputStream())); + client.executeMethod(postMethod); + assertEquals("Invalid Response Code", HttpStatus.SC_ACCEPTED, postMethod.getStatusCode()); + assertEquals("Response retrieved", 0, postMethod.getResponseContentLength()); + } + + public void testResponse() throws IOException { + PostMethod postMethod = new PostMethod("http://localhost:8888/service"); + postMethod.addRequestHeader(CONTENT_TYPE, "text/xml"); + postMethod.addRequestHeader(SOAP_ACTION, "http://springframework.org/spring-ws/Response"); + Resource soapRequest = new ClassPathResource("soapRequest.xml", MessageDispatcherServletIntegrationTest.class); + postMethod.setRequestEntity(new InputStreamRequestEntity(soapRequest.getInputStream())); + client.executeMethod(postMethod); + assertEquals("Invalid Response Code", HttpStatus.SC_OK, postMethod.getStatusCode()); + assertTrue("No Response retrieved", postMethod.getResponseContentLength() > 0); + } + + public void testNoEndpoint() throws IOException { + PostMethod postMethod = new PostMethod("http://localhost:8888/service"); + postMethod.addRequestHeader(CONTENT_TYPE, "text/xml"); + postMethod.addRequestHeader(SOAP_ACTION, "http://springframework.org/spring-ws/NoEndpoint"); + Resource soapRequest = new ClassPathResource("soapRequest.xml", MessageDispatcherServletIntegrationTest.class); + postMethod.setRequestEntity(new InputStreamRequestEntity(soapRequest.getInputStream())); + client.executeMethod(postMethod); + assertEquals("Invalid Response Code", HttpStatus.SC_NOT_FOUND, postMethod.getStatusCode()); + assertEquals("Response retrieved", 0, postMethod.getResponseContentLength()); + } + + public void testFault() throws IOException { + PostMethod postMethod = new PostMethod("http://localhost:8888/service"); + postMethod.addRequestHeader(CONTENT_TYPE, "text/xml"); + postMethod.addRequestHeader(SOAP_ACTION, "http://springframework.org/spring-ws/Fault"); + Resource soapRequest = new ClassPathResource("soapRequest.xml", MessageDispatcherServletIntegrationTest.class); + postMethod.setRequestEntity(new InputStreamRequestEntity(soapRequest.getInputStream())); + client.executeMethod(postMethod); + assertEquals("Invalid Response Code", HttpStatus.SC_INTERNAL_SERVER_ERROR, postMethod.getStatusCode()); + assertTrue("No Response retrieved", postMethod.getResponseContentLength() > 0); + } + + +} diff --git a/core/src/test/java/org/springframework/ws/transport/http/NoResponseEndpoint.java b/core/src/test/java/org/springframework/ws/transport/http/NoResponseEndpoint.java new file mode 100644 index 00000000..38e77ef2 --- /dev/null +++ b/core/src/test/java/org/springframework/ws/transport/http/NoResponseEndpoint.java @@ -0,0 +1,27 @@ +/* + * 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.transport.http; + +import org.springframework.ws.context.MessageContext; +import org.springframework.ws.server.endpoint.MessageEndpoint; + +/** @author Arjen Poutsma */ +public class NoResponseEndpoint implements MessageEndpoint { + + public void invoke(MessageContext messageContext) throws Exception { + } +} diff --git a/core/src/test/java/org/springframework/ws/transport/http/ResponseEndpoint.java b/core/src/test/java/org/springframework/ws/transport/http/ResponseEndpoint.java new file mode 100644 index 00000000..4d876d3e --- /dev/null +++ b/core/src/test/java/org/springframework/ws/transport/http/ResponseEndpoint.java @@ -0,0 +1,28 @@ +/* + * 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.transport.http; + +import org.springframework.ws.context.MessageContext; +import org.springframework.ws.server.endpoint.MessageEndpoint; + +/** @author Arjen Poutsma */ +public class ResponseEndpoint implements MessageEndpoint { + + public void invoke(MessageContext messageContext) throws Exception { + messageContext.getResponse(); + } +} diff --git a/core/src/test/resources/org/springframework/ws/transport/http/WEB-INF/spring-ws-servlet.xml b/core/src/test/resources/org/springframework/ws/transport/http/WEB-INF/spring-ws-servlet.xml new file mode 100644 index 00000000..3e6c9225 --- /dev/null +++ b/core/src/test/resources/org/springframework/ws/transport/http/WEB-INF/spring-ws-servlet.xml @@ -0,0 +1,24 @@ + + + + + + + noResponseEndpoint + responseEndpoint + faultEndpoint + + + + + + + + + + + diff --git a/core/src/test/resources/org/springframework/ws/transport/http/soapRequest.xml b/core/src/test/resources/org/springframework/ws/transport/http/soapRequest.xml new file mode 100644 index 00000000..199de8ec --- /dev/null +++ b/core/src/test/resources/org/springframework/ws/transport/http/soapRequest.xml @@ -0,0 +1,7 @@ + + + + DIS + + + \ No newline at end of file