Client-side support seems finished

This commit is contained in:
Arjen Poutsma
2007-01-13 20:07:08 +00:00
parent 962caeab1e
commit 54b63aec9f
11 changed files with 361 additions and 110 deletions

View File

@@ -25,7 +25,10 @@ import javax.xml.transform.TransformerException;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.support.WebServiceAccessor;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.transport.WebServiceMessageSender;
/**
* @author Arjen Poutsma
@@ -36,6 +39,29 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService
private Unmarshaller unmarshaller;
/**
* Creates a new <code>WebServiceTemplate</code>.
* <p/>
* <b>Note</b> that the message factory and message sender properties have to be set before this template can be
* used.
*
* @see #setMessageFactory(org.springframework.ws.WebServiceMessageFactory)
* @see #setMessageSender(org.springframework.ws.transport.WebServiceMessageSender)
*/
public WebServiceTemplate() {
}
/**
* Creates a new <code>WebServiceTemplate</code> based on the given message factory and message sender.
*
* @param messageFactory the message factory to use
* @param messageSender the message sender to use
*/
public WebServiceTemplate(WebServiceMessageFactory messageFactory, WebServiceMessageSender messageSender) {
setMessageFactory(messageFactory);
setMessageSender(messageSender);
}
/**
* Returns the marshaller for this template.
*/

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ws.client;
package org.springframework.ws.client.support;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

View File

@@ -0,0 +1,169 @@
/*
* 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.client.support;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.WebServiceTemplate;
import org.springframework.ws.transport.WebServiceMessageSender;
/**
* Convenient super class for application classes that need Web service access.
* <p/>
* Requires a {@link org.springframework.ws.WebServiceMessageFactory} and {@link org.springframework.ws.transport.WebServiceMessageSender},
* or a {@link org.springframework.ws.client.WebServiceTemplate} instance to be set. It will create its own
* <code>WebServiceTemplate</code> if <code>WebServiceMessageFactory</code> and <code>WebServiceMessageSender</code> are
* passed in.
* <p/>
* In addition to the message factory and sender properties, this gateway offers {@link
* org.springframework.oxm.Marshaller} and {@link org.springframework.oxm.Unmarshaller} properties. Setting these is
* required when the {@link org.springframework.ws.client.WebServiceTemplate#marshalSendAndReceive(Object) marshalling
* methods} of the template are to be used.
*
* @author Arjen Poutsma
* @see #setMessageFactory(org.springframework.ws.WebServiceMessageFactory)
* @see #setMessageSender(org.springframework.ws.transport.WebServiceMessageSender)
* @see org.springframework.ws.client.WebServiceTemplate
* @see #setMarshaller(org.springframework.oxm.Marshaller)
*/
public abstract class WebServiceGatewaySupport implements InitializingBean {
protected final Log logger = LogFactory.getLog(getClass());
private WebServiceMessageFactory messageFactory;
private WebServiceMessageSender messageSender;
private WebServiceTemplate webServiceTemplate;
private Marshaller marshaller;
private Unmarshaller unmarshaller;
/**
* Returns the <code>WebServiceMessageFactory</code> used by the gateway.
*/
public final WebServiceMessageFactory getMessageFactory() {
return messageFactory;
}
/**
* Set the <code>WebServiceMessageFactory</code> to be used by the gateway.
*/
public final void setMessageFactory(WebServiceMessageFactory messageFactory) {
this.messageFactory = messageFactory;
}
/**
* Returns the <code>WebServiceMessageSender</code> used by the gateway.
*/
public final WebServiceMessageSender getMessageSender() {
return messageSender;
}
/**
* Sets the <code>WebServiceMessageSender</code> to be used by the gateway.
*/
public final void setMessageSender(WebServiceMessageSender messageSender) {
this.messageSender = messageSender;
}
/**
* Returns the <code>WebServiceTemplate</code> for the gateway.
*/
public final WebServiceTemplate getWebServiceTemplate() {
return webServiceTemplate;
}
/**
* Sets the <code>WebServiceTemplate</code> to be used by the gateway.
*/
public final void setWebServiceTemplate(WebServiceTemplate webServiceTemplate) {
this.webServiceTemplate = webServiceTemplate;
}
/**
* Returns the <code>Marshaller</code> used by the gateway.
*/
public final Marshaller getMarshaller() {
return marshaller;
}
/**
* Sets the <code>Marshaller</code> used by the gateway. Setting this property is only required if the marshalling
* functionality of <code>WebServiceTemplate</code> is to be used.
*
* @see org.springframework.ws.client.WebServiceTemplate#marshalSendAndReceive
*/
public void setMarshaller(Marshaller marshaller) {
this.marshaller = marshaller;
}
/**
* Returns the <code>Unmarshaller</code> used by the gateway.
*/
public final Unmarshaller getUnmarshaller() {
return unmarshaller;
}
/**
* Sets the <code>Unmarshaller</code> used by the gateway. Setting this property is only required if the marshalling
* functionality of <code>WebServiceTemplate</code> is to be used.
*
* @see org.springframework.ws.client.WebServiceTemplate#marshalSendAndReceive
*/
public final void setUnmarshaller(Unmarshaller unmarshaller) {
this.unmarshaller = unmarshaller;
}
public final void afterPropertiesSet() throws IllegalArgumentException, BeanInitializationException {
if (webServiceTemplate == null && messageFactory != null && messageSender != null) {
webServiceTemplate = new WebServiceTemplate(messageFactory, messageSender);
if (marshaller != null) {
webServiceTemplate.setMarshaller(marshaller);
}
if (unmarshaller != null) {
webServiceTemplate.setUnmarshaller(unmarshaller);
}
}
if (webServiceTemplate == null) {
throw new IllegalArgumentException("messageFactory and messageSender or webServiceTemplate is required");
}
try {
initGateway();
}
catch (Exception ex) {
throw new BeanInitializationException("Initialization of Web service gateway failed: " + ex.getMessage(),
ex);
}
}
/**
* Subclasses can override this for custom initialization behavior. Gets called after population of this instance's
* bean properties.
*
* @throws java.lang.Exception if initialization fails
*/
protected void initGateway() throws Exception {
}
}

View File

@@ -5,6 +5,9 @@ import java.io.IOException;
import org.springframework.ws.context.MessageContext;
/**
* Defines the methods for classes capable of sending and receiving {@link org.springframework.ws.WebServiceMessage}
* instances across a transport.
*
* @author Arjen Poutsma
*/
public interface WebServiceMessageSender {

View File

@@ -0,0 +1,53 @@
/*
* 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.net.URL;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import org.springframework.ws.transport.WebServiceMessageSender;
/**
* Abstract base class for {@link org.springframework.ws.transport.WebServiceMessageSender} implementations that use
* HTTP.
*
* @author Arjen Poutsma
*/
public abstract class AbstractHttpWebServiceMessageSender implements WebServiceMessageSender, InitializingBean {
private URL url;
/**
* Returns the url used by this message sender.
*/
public URL getUrl() {
return url;
}
/**
* Sets the url used by this message sender.
*/
public void setUrl(URL url) {
this.url = url;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(url, "url is required");
}
}

View File

@@ -17,7 +17,6 @@
package org.springframework.ws.transport.http;
import java.io.IOException;
import java.net.URL;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
@@ -26,7 +25,6 @@ import org.apache.commons.httpclient.methods.PostMethod;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.transport.TransportInputStream;
import org.springframework.ws.transport.WebServiceMessageSender;
/**
* <code>WebServiceMessageSender</code> implementation that uses <a href="http://jakarta.apache.org/commons/httpclient">Jakarta
@@ -38,12 +36,10 @@ import org.springframework.ws.transport.WebServiceMessageSender;
* @author Arjen Poutsma
* @see org.springframework.ws.transport.http.HttpUrlConnectionMessageSender
*/
public class CommonsHttpMessageSender implements WebServiceMessageSender {
public class CommonsHttpMessageSender extends AbstractHttpWebServiceMessageSender {
private HttpClient httpClient;
private URL url;
/**
* Create a new instance of the <code>CommonsHttpMessageSender</code> with a default <code>HttpClient</code> that
* uses a default <code>MultiThreadedHttpConnectionManager</code>.
@@ -166,18 +162,4 @@ public class CommonsHttpMessageSender implements WebServiceMessageSender {
}
}
}
/**
* Returns the url used by this message sender.
*/
public URL getUrl() {
return url;
}
/**
* Sets the url used by this message sender.
*/
public void setUrl(URL url) {
this.url = url;
}
}

View File

@@ -18,14 +18,12 @@ package org.springframework.ws.transport.http;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.transport.TransportInputStream;
import org.springframework.ws.transport.TransportOutputStream;
import org.springframework.ws.transport.WebServiceMessageSender;
/**
* <code>WebServiceMessageSender</code> implementation that uses standard J2SE facilities to execute POST requests,
@@ -38,26 +36,10 @@ import org.springframework.ws.transport.WebServiceMessageSender;
* @author Arjen Poutsma
* @see java.net.HttpURLConnection
*/
public class HttpUrlConnectionMessageSender implements WebServiceMessageSender {
public class HttpUrlConnectionMessageSender extends AbstractHttpWebServiceMessageSender {
private static final String HTTP_METHOD_POST = "POST";
private URL url;
/**
* Returns the url used by this message sender.
*/
public URL getUrl() {
return url;
}
/**
* Sets the url used by this message sender.
*/
public void setUrl(URL url) {
this.url = url;
}
public void sendAndReceive(MessageContext messageContext) throws IOException {
HttpURLConnection connection = openConnection();
try {
@@ -123,4 +105,5 @@ public class HttpUrlConnectionMessageSender implements WebServiceMessageSender {
}
}
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ws.client;
package org.springframework.ws.client.support;
import junit.framework.TestCase;
import org.easymock.MockControl;

View File

@@ -16,21 +16,37 @@
package org.springframework.ws.transport.http;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.stream.StreamSource;
import junit.framework.TestCase;
import org.custommonkey.xmlunit.XMLTestCase;
import org.custommonkey.xmlunit.XMLUnit;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.servlet.Context;
import org.mortbay.jetty.servlet.ServletHolder;
import org.springframework.util.FileCopyUtils;
import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.soap.saaj.SaajSoapMessage;
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
import org.springframework.xml.transform.StringResult;
import org.springframework.xml.transform.StringSource;
public abstract class AbstractHttpWebServiceMessageSenderTestCase extends TestCase {
public abstract class AbstractHttpWebServiceMessageSenderTestCase extends XMLTestCase {
protected Server jettyServer;
@@ -40,33 +56,103 @@ public abstract class AbstractHttpWebServiceMessageSenderTestCase extends TestCa
protected static final String URL = "http://localhost:8888";
protected static final String REQUEST = "<Request xmlns='http://springframework.org/spring-ws'/>";
protected static final String EXPECTED_SOAP_REQUEST =
"<SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>" + "<SOAP-ENV:Header/>" +
"<SOAP-ENV:Body>" + REQUEST + "</SOAP-ENV:Body>" + "</SOAP-ENV:Envelope>";
protected static final String RESPONSE = "<Response xmlns='http://springframework.org/spring-ws'/>";
protected Transformer transformer;
protected AbstractHttpWebServiceMessageSender messageSender;
private MessageFactory messageFactory;
private String receivedRequest;
private String receivedHeader;
protected final void setUp() throws Exception {
onSetUp();
messageFactory = MessageFactory.newInstance();
transformer = TransformerFactory.newInstance().newTransformer();
jettyServer = new Server(8888);
Context root = new Context(jettyServer, "/");
root.addServlet(new ServletHolder(new EchoServlet()), "/*");
root.addServlet(new ServletHolder(new ResponseServlet()), "/response");
root.addServlet(new ServletHolder(new NoResponseServlet()), "/noresponse");
jettyServer.start();
messageSender = createMessageSender();
XMLUnit.setIgnoreWhitespace(true);
}
protected void onSetUp() throws Exception {
}
protected abstract AbstractHttpWebServiceMessageSender createMessageSender();
protected final void tearDown() throws Exception {
jettyServer.stop();
}
private static class EchoServlet extends GenericServlet {
public void testSendAndReceiveResponse() throws Exception {
messageSender.setUrl(new URL("http://localhost:8888/response"));
SOAPMessage saajRequest = messageFactory.createMessage();
saajRequest.getMimeHeaders().addHeader(HEADER_NAME, HEADER_VALUE);
transformer.transform(new StringSource(REQUEST), new DOMResult(saajRequest.getSOAPBody()));
SaajSoapMessage request = new SaajSoapMessage(saajRequest);
MessageContext context = new DefaultMessageContext(request, new SaajSoapMessageFactory(messageFactory));
messageSender.sendAndReceive(context);
assertXMLEqual(EXPECTED_SOAP_REQUEST, receivedRequest.toString());
assertEquals("Invalid header value received", HEADER_VALUE, receivedHeader);
assertTrue("No response", context.hasResponse());
ByteArrayOutputStream os = new ByteArrayOutputStream();
context.getResponse().writeTo(os);
assertXMLEqual(RESPONSE, os.toString("UTF-8"));
}
public void testSendAndReceiveNoResponse() throws Exception {
messageSender.setUrl(new URL("http://localhost:8888/noresponse"));
SOAPMessage saajRequest = messageFactory.createMessage();
transformer.transform(new StringSource(REQUEST), new DOMResult(saajRequest.getSOAPBody()));
SaajSoapMessage request = new SaajSoapMessage(saajRequest);
MessageContext context = new DefaultMessageContext(request, new SaajSoapMessageFactory(messageFactory));
messageSender.sendAndReceive(context);
assertFalse("Response", context.hasResponse());
}
private class ResponseServlet extends GenericServlet {
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
HttpServletRequest httpServletRequest = (HttpServletRequest) req;
HttpServletResponse httpServletResponse = (HttpServletResponse) res;
httpServletResponse.setStatus(HttpServletResponse.SC_OK);
// assertEquals("Invalid header", HEADER_VALUE, httpServletRequest.getHeader(HEADER_NAME));
try {
StringResult requestResult = new StringResult();
transformer.transform(new StreamSource(req.getInputStream()), requestResult);
receivedRequest = requestResult.toString();
receivedHeader = ((HttpServletRequest) req).getHeader(HEADER_NAME);
httpServletResponse.addHeader("Content-Type", "text/xml");
httpServletResponse.addHeader(HEADER_NAME, HEADER_VALUE);
FileCopyUtils.copy(req.getInputStream(), res.getOutputStream());
HttpServletResponse httpServletResponse = (HttpServletResponse) res;
httpServletResponse.setStatus(HttpServletResponse.SC_OK);
httpServletResponse.addHeader("Content-Type", "text/xml");
FileCopyUtils.copy(RESPONSE.getBytes("UTF-8"), res.getOutputStream());
}
catch (TransformerException ex) {
throw new ServletException(ex);
}
}
}
private class NoResponseServlet extends GenericServlet {
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
try {
StringResult requestResult = new StringResult();
transformer.transform(new StreamSource(req.getInputStream()), requestResult);
receivedRequest = requestResult.toString();
receivedHeader = ((HttpServletRequest) req).getHeader(HEADER_NAME);
HttpServletResponse httpServletResponse = (HttpServletResponse) res;
httpServletResponse.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
catch (TransformerException ex) {
throw new ServletException(ex);
}
}
}
}

View File

@@ -16,33 +16,10 @@
package org.springframework.ws.transport.http;
import java.net.URL;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPMessage;
import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
public class CommonsHttpMessageSenderTest extends AbstractHttpWebServiceMessageSenderTestCase {
private CommonsHttpMessageSender sender;
private MessageFactory messageFactory;
protected void onSetUp() throws Exception {
sender = new CommonsHttpMessageSender();
sender.setUrl(new URL(URL));
messageFactory = MessageFactory.newInstance();
protected AbstractHttpWebServiceMessageSender createMessageSender() {
return new CommonsHttpMessageSender();
}
public void testSend() throws Exception {
SOAPMessage message = messageFactory.createMessage();
message.getMimeHeaders().addHeader(HEADER_NAME, HEADER_VALUE);
MessageContext context = new DefaultMessageContext(new SaajSoapMessageFactory(messageFactory));
sender.sendAndReceive(context);
assertTrue("No response", context.hasResponse());
context.getResponse().writeTo(System.out);
}
}

View File

@@ -16,37 +16,9 @@
package org.springframework.ws.transport.http;
import java.net.URL;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPMessage;
import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.soap.saaj.SaajSoapMessage;
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
public class HttpUrlConnectionMessageSenderTest extends AbstractHttpWebServiceMessageSenderTestCase {
private HttpUrlConnectionMessageSender sender;
private MessageFactory messageFactory;
protected void onSetUp() throws Exception {
sender = new HttpUrlConnectionMessageSender();
sender.setUrl(new URL(URL));
messageFactory = MessageFactory.newInstance();
}
public void testSend() throws Exception {
SOAPMessage message = messageFactory.createMessage();
message.getMimeHeaders().addHeader(HEADER_NAME, HEADER_VALUE);
SaajSoapMessage request = new SaajSoapMessage(message);
MessageContext context = new DefaultMessageContext(request, new SaajSoapMessageFactory(messageFactory));
// AxiomSoapMessageFactory soapMessageFactory = new AxiomSoapMessageFactory();
// MessageContext context = new DefaultMessageContext(soapMessageFactory);
sender.sendAndReceive(context);
assertTrue("No response", context.hasResponse());
context.getResponse().writeTo(System.out);
protected AbstractHttpWebServiceMessageSender createMessageSender() {
return new HttpUrlConnectionMessageSender();
}
}