diff --git a/core/src/main/java/org/springframework/ws/client/core/WebServiceOperations.java b/core/src/main/java/org/springframework/ws/client/core/WebServiceOperations.java
index 5e9ff128..fe4a2910 100644
--- a/core/src/main/java/org/springframework/ws/client/core/WebServiceOperations.java
+++ b/core/src/main/java/org/springframework/ws/client/core/WebServiceOperations.java
@@ -34,6 +34,8 @@ public interface WebServiceOperations {
/**
* Sends a web service message that contains the given payload, marshalled by the configured
* Marshaller. Returns the unmarshalled payload of the response message, if any.
+ *
null if no response is given
@@ -44,10 +46,27 @@ public interface WebServiceOperations {
*/
Object marshalSendAndReceive(Object requestPayload) throws XmlMappingException, WebServiceClientException;
+ /**
+ * Sends a web service message that contains the given payload, marshalled by the configured
+ * Marshaller. Returns the unmarshalled payload of the response message, if any.
+ *
+ * @param uri the URI to send the message to
+ * @param requestPayload the object to marshal into the request message payload
+ * @return the unmarshalled payload of the response message, or null if no response is given
+ * @throws XmlMappingException if there is a problem marshalling or unmarshalling
+ * @throws WebServiceClientException if there is a problem sending or receiving the message
+ * @see WebServiceTemplate#setMarshaller(org.springframework.oxm.Marshaller)
+ * @see WebServiceTemplate#setUnmarshaller(org.springframework.oxm.Unmarshaller)
+ */
+ Object marshalSendAndReceive(String uri, Object requestPayload)
+ throws XmlMappingException, WebServiceClientException;
+
/**
* Sends a web service message that contains the given payload, marshalled by the configured
* Marshaller. Returns the unmarshalled payload of the response message, if any. The given callback
* allows changing of the request message after the payload has been marshalled to it.
+ *
+ * This will only work with a default specified!
*
* @param requestPayload the object to marshal into the request message payload
* @param requestCallback callback to change message, can be null
@@ -60,9 +79,28 @@ public interface WebServiceOperations {
Object marshalSendAndReceive(Object requestPayload, WebServiceMessageCallback requestCallback)
throws XmlMappingException, WebServiceClientException;
+ /**
+ * Sends a web service message that contains the given payload, marshalled by the configured
+ * Marshaller. Returns the unmarshalled payload of the response message, if any. The given callback
+ * allows changing of the request message after the payload has been marshalled to it.
+ *
+ * @param uri the URI to send the message to
+ * @param requestPayload the object to marshal into the request message payload
+ * @param requestCallback callback to change message, can be null
+ * @return the unmarshalled payload of the response message, or null if no response is given
+ * @throws XmlMappingException if there is a problem marshalling or unmarshalling
+ * @throws WebServiceClientException if there is a problem sending or receiving the message
+ * @see WebServiceTemplate#setMarshaller(org.springframework.oxm.Marshaller)
+ * @see WebServiceTemplate#setUnmarshaller(org.springframework.oxm.Unmarshaller)
+ */
+ Object marshalSendAndReceive(String uri, Object requestPayload, WebServiceMessageCallback requestCallback)
+ throws XmlMappingException, WebServiceClientException;
+
/**
* Sends a web service message that contains the given payload, reading the result with a
* SourceExtractor.
+ *
+ * This will only work with a default specified!
*
* @param requestPayload the payload of the request message
* @param responseExtractor object that will extract results
@@ -71,11 +109,26 @@ public interface WebServiceOperations {
*/
Object sendAndReceive(Source requestPayload, SourceExtractor responseExtractor) throws WebServiceClientException;
+ /**
+ * Sends a web service message that contains the given payload, reading the result with a
+ * SourceExtractor.
+ *
+ * @param uri the URI to send the message to
+ * @param requestPayload the payload of the request message
+ * @param responseExtractor object that will extract results
+ * @return an arbitrary result object, as returned by the SourceExtractor
+ * @throws WebServiceClientException if there is a problem sending or receiving the message
+ */
+ Object sendAndReceive(String uri, Source requestPayload, SourceExtractor responseExtractor)
+ throws WebServiceClientException;
+
/**
* Sends a web service message that contains the given payload, reading the result with a
* SourceExtractor.
*
* The given callback allows changing of the request message after the payload has been written to it.
+ *
+ * This will only work with a default specified!
*
* @param requestPayload the payload of the request message
* @param requestCallback callback to change message, can be null
@@ -87,9 +140,29 @@ public interface WebServiceOperations {
WebServiceMessageCallback requestCallback,
SourceExtractor responseExtractor) throws WebServiceClientException;
+ /**
+ * Sends a web service message that contains the given payload, reading the result with a
+ * SourceExtractor.
+ *
+ * The given callback allows changing of the request message after the payload has been written to it.
+ *
+ * @param uri the URI to send the message to
+ * @param requestPayload the payload of the request message
+ * @param requestCallback callback to change message, can be null
+ * @param responseExtractor object that will extract results
+ * @return an arbitrary result object, as returned by the SourceExtractor
+ * @throws WebServiceClientException if there is a problem sending or receiving the message
+ */
+ Object sendAndReceive(String uri,
+ Source requestPayload,
+ WebServiceMessageCallback requestCallback,
+ SourceExtractor responseExtractor) throws WebServiceClientException;
+
/**
* Sends a web service message that contains the given payload. Writes the response, if any, to the given
* Result.
+ *
+ * This will only work with a default specified!
*
* @param requestPayload the payload of the request message
* @param responseResult the result to write the response payload to
@@ -97,11 +170,24 @@ public interface WebServiceOperations {
*/
void sendAndReceive(Source requestPayload, Result responseResult) throws WebServiceClientException;
+ /**
+ * Sends a web service message that contains the given payload. Writes the response, if any, to the given
+ * Result.
+ *
+ * @param uri the URI to send the message to
+ * @param requestPayload the payload of the request message
+ * @param responseResult the result to write the response payload to
+ * @throws WebServiceClientException if there is a problem sending or receiving the message
+ */
+ void sendAndReceive(String uri, Source requestPayload, Result responseResult) throws WebServiceClientException;
+
/**
* Sends a web service message that contains the given payload. Writes the response, if any, to the given
* Result.
*
* The given callback allows changing of the request message after the payload has been written to it.
+ *
+ * This will only work with a default specified!
*
* @param requestPayload the payload of the request message
* @param requestCallback callback to change message, can be null
@@ -111,9 +197,28 @@ public interface WebServiceOperations {
void sendAndReceive(Source requestPayload, WebServiceMessageCallback requestCallback, Result responseResult)
throws WebServiceClientException;
+ /**
+ * Sends a web service message that contains the given payload. Writes the response, if any, to the given
+ * Result.
+ *
+ * The given callback allows changing of the request message after the payload has been written to it.
+ *
+ * @param uri the URI to send the message to
+ * @param requestPayload the payload of the request message
+ * @param requestCallback callback to change message, can be null
+ * @param responseResult the result to write the response payload to
+ * @throws WebServiceClientException if there is a problem sending or receiving the message
+ */
+ void sendAndReceive(String uri,
+ Source requestPayload,
+ WebServiceMessageCallback requestCallback,
+ Result responseResult) throws WebServiceClientException;
+
/**
* Sends a web service message that can be manipulated with the given callback, reading the result with a
* WebServiceMessageExtractor.
+ *
+ * This will only work with a default specified!
*
* @param requestCallback the requestCallback to be used for manipulating the request message
* @param responseExtractor object that will extract results
@@ -127,10 +232,39 @@ public interface WebServiceOperations {
* Sends a web service message that can be manipulated with the given callback, reading the result with a
* WebServiceMessageExtractor.
*
+ * @param uri the URI to send the message to
+ * @param requestCallback the requestCallback to be used for manipulating the request message
+ * @param responseExtractor object that will extract results
+ * @return an arbitrary result object, as returned by the WebServiceMessageExtractor
+ * @throws WebServiceClientException if there is a problem sending or receiving the message
+ */
+ Object sendAndReceive(String uri,
+ WebServiceMessageCallback requestCallback,
+ WebServiceMessageExtractor responseExtractor) throws WebServiceClientException;
+
+ /**
+ * Sends a web service message that can be manipulated with the given callback, reading the result with a
+ * WebServiceMessageExtractor.
+ *
+ * This will only work with a default specified!
+ *
* @param requestCallback the callback to be used for manipulating the request message
* @param responseCallback the callback to be used for manipulating the response message
* @throws WebServiceClientException if there is a problem sending or receiving the message
*/
void sendAndReceive(WebServiceMessageCallback requestCallback, WebServiceMessageCallback responseCallback)
throws WebServiceClientException;
+
+ /**
+ * Sends a web service message that can be manipulated with the given callback, reading the result with a
+ * WebServiceMessageExtractor.
+ *
+ * @param uri the URI to send the message to
+ * @param requestCallback the callback to be used for manipulating the request message
+ * @param responseCallback the callback to be used for manipulating the response message
+ * @throws WebServiceClientException if there is a problem sending or receiving the message
+ */
+ void sendAndReceive(String uri,
+ WebServiceMessageCallback requestCallback,
+ WebServiceMessageCallback responseCallback) throws WebServiceClientException;
}
diff --git a/core/src/main/java/org/springframework/ws/client/core/WebServiceTemplate.java b/core/src/main/java/org/springframework/ws/client/core/WebServiceTemplate.java
index efd47e85..206014d0 100644
--- a/core/src/main/java/org/springframework/ws/client/core/WebServiceTemplate.java
+++ b/core/src/main/java/org/springframework/ws/client/core/WebServiceTemplate.java
@@ -18,6 +18,8 @@ package org.springframework.ws.client.core;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
@@ -35,17 +37,15 @@ import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
+import org.springframework.util.ObjectUtils;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.WebServiceIOException;
import org.springframework.ws.client.WebServiceTransformerException;
import org.springframework.ws.client.WebServiceTransportException;
import org.springframework.ws.client.support.WebServiceAccessor;
-import org.springframework.ws.context.MessageContext;
import org.springframework.ws.transport.FaultAwareWebServiceConnection;
import org.springframework.ws.transport.TransportException;
-import org.springframework.ws.transport.TransportInputStream;
-import org.springframework.ws.transport.TransportOutputStream;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.WebServiceMessageSender;
import org.springframework.ws.transport.support.DefaultStrategiesHelper;
@@ -69,24 +69,39 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService
private FaultResolver faultResolver = new SimpleFaultResolver();
- private DefaultStrategiesHelper defaultStrategiesHelper;
+ private String defaultUri;
/** Creates a new WebServiceTemplate using default settings. */
public WebServiceTemplate() {
- Resource resource = new ClassPathResource(ClassUtils.getShortName(getClass()) + ".properties", getClass());
- defaultStrategiesHelper = new DefaultStrategiesHelper(resource);
}
/**
- * Creates a new WebServiceTemplate based on the given message factory and message sender.
+ * Creates a new WebServiceTemplate based on the given message factory.
*
* @param messageFactory the message factory to use
- * @param messageSender the message sender to use
*/
- public WebServiceTemplate(WebServiceMessageFactory messageFactory, WebServiceMessageSender messageSender) {
- this();
+ public WebServiceTemplate(WebServiceMessageFactory messageFactory) {
setMessageFactory(messageFactory);
- setMessageSender(messageSender);
+ }
+
+ /** Returns the default URI to be used on operations that do not have a URI parameter. */
+ public String getDefaultUri() {
+ return defaultUri;
+ }
+
+ /**
+ * Set the default URI to be used on operations that do not have a URI parameter.
+ *
+ * @see #marshalSendAndReceive(Object)
+ * @see #marshalSendAndReceive(Object,WebServiceMessageCallback)
+ * @see #sendAndReceive(Source,Result)
+ * @see #sendAndReceive(Source,WebServiceMessageCallback,Result)
+ * @see #sendAndReceive(Source,SourceExtractor)
+ * @see #sendAndReceive(Source,WebServiceMessageCallback,SourceExtractor)
+ * @see #sendAndReceive(WebServiceMessageCallback,WebServiceMessageCallback)
+ */
+ public void setDefaultUri(String uri) {
+ this.defaultUri = uri;
}
/** Returns the marshaller for this template. */
@@ -120,13 +135,19 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService
this.faultResolver = faultResolver;
}
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ public final void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ Resource resource = new ClassPathResource(ClassUtils.getShortName(getClass()) + ".properties", getClass());
+ DefaultStrategiesHelper defaultStrategiesHelper = new DefaultStrategiesHelper(resource);
if (getMessageFactory() == null) {
- initWebServiceMessageFactory(applicationContext);
+ initWebServiceMessageFactory(defaultStrategiesHelper, applicationContext);
+ }
+ if (ObjectUtils.isEmpty(getMessageSenders())) {
+ initWebServiceMessageSenders(defaultStrategiesHelper, applicationContext);
}
}
- private void initWebServiceMessageFactory(ApplicationContext applicationContext)
+ private void initWebServiceMessageFactory(DefaultStrategiesHelper defaultStrategiesHelper,
+ ApplicationContext applicationContext)
throws BeanInitializationException {
WebServiceMessageFactory messageFactory = (WebServiceMessageFactory) defaultStrategiesHelper
.getDefaultStrategy(WebServiceMessageFactory.class, applicationContext);
@@ -144,6 +165,28 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService
setMessageFactory(messageFactory);
}
+ private void initWebServiceMessageSenders(DefaultStrategiesHelper defaultStrategiesHelper,
+ ApplicationContext applicationContext) {
+ List messageSenders =
+ defaultStrategiesHelper.getDefaultStrategies(WebServiceMessageSender.class, applicationContext);
+ if (logger.isInfoEnabled()) {
+ logger.info("Using default message senders " + messageSenders);
+ }
+ for (Iterator iterator = messageSenders.iterator(); iterator.hasNext();) {
+ WebServiceMessageSender messageSender = (WebServiceMessageSender) iterator.next();
+ if (messageSender instanceof InitializingBean) {
+ try {
+ ((InitializingBean) messageSender).afterPropertiesSet();
+ }
+ catch (Exception ex) {
+ throw new BeanInitializationException("Could not initialize message factory", ex);
+ }
+ }
+ }
+ setMessageSenders(
+ (WebServiceMessageSender[]) messageSenders.toArray(new WebServiceMessageSender[messageSenders.size()]));
+ }
+
/*
* Marshalling methods
*/
@@ -152,14 +195,24 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService
return marshalSendAndReceive(requestPayload, null);
}
+ public Object marshalSendAndReceive(String uri, final Object requestPayload) {
+ return marshalSendAndReceive(requestPayload, null);
+ }
+
public Object marshalSendAndReceive(final Object requestPayload, final WebServiceMessageCallback requestCallback) {
+ return marshalSendAndReceive(getDefaultUri(), requestPayload, requestCallback);
+ }
+
+ public Object marshalSendAndReceive(String uri,
+ final Object requestPayload,
+ final WebServiceMessageCallback requestCallback) {
if (getMarshaller() == null) {
throw new IllegalStateException("No marshaller registered. Check configuration of WebServiceTemplate.");
}
if (getUnmarshaller() == null) {
throw new IllegalStateException("No unmarshaller registered. Check configuration of WebServiceTemplate.");
}
- return sendAndReceive(new WebServiceMessageCallback() {
+ return sendAndReceive(uri, new WebServiceMessageCallback() {
public void doInMessage(WebServiceMessage message) throws IOException {
getMarshaller().marshal(requestPayload, message.getPayloadResult());
@@ -183,12 +236,23 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService
sendAndReceive(requestPayload, null, responseResult);
}
+ public void sendAndReceive(String uri, Source requestPayload, Result responseResult) {
+ sendAndReceive(uri, requestPayload, null, responseResult);
+ }
+
public void sendAndReceive(Source requestPayload,
WebServiceMessageCallback requestCallback,
final Result responseResult) {
+ sendAndReceive(getDefaultUri(), requestPayload, requestCallback, responseResult);
+ }
+
+ public void sendAndReceive(String uri,
+ Source requestPayload,
+ WebServiceMessageCallback requestCallback,
+ final Result responseResult) {
try {
final Transformer transformer = createTransformer();
- doSendAndReceive(transformer, requestPayload, requestCallback, new SourceExtractor() {
+ doSendAndReceive(uri, transformer, requestPayload, requestCallback, new SourceExtractor() {
public Object extractData(Source source) throws IOException {
try {
@@ -214,24 +278,36 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService
return sendAndReceive(requestPayload, null, responseExtractor);
}
+ public Object sendAndReceive(String uri, final Source requestPayload, final SourceExtractor responseExtractor) {
+ return sendAndReceive(uri, requestPayload, null, responseExtractor);
+ }
+
public Object sendAndReceive(final Source requestPayload,
final WebServiceMessageCallback requestCallback,
final SourceExtractor responseExtractor) {
+ return sendAndReceive(getDefaultUri(), requestPayload, requestCallback, responseExtractor);
+ }
+
+ public Object sendAndReceive(String uri,
+ final Source requestPayload,
+ final WebServiceMessageCallback requestCallback,
+ final SourceExtractor responseExtractor) {
try {
- return doSendAndReceive(createTransformer(), requestPayload, requestCallback, responseExtractor);
+ return doSendAndReceive(uri, createTransformer(), requestPayload, requestCallback, responseExtractor);
}
catch (TransformerConfigurationException ex) {
throw new WebServiceTransformerException("Could not create transformer", ex);
}
}
- private Object doSendAndReceive(final Transformer transformer,
+ private Object doSendAndReceive(String uri,
+ final Transformer transformer,
final Source requestPayload,
final WebServiceMessageCallback requestCallback,
final SourceExtractor responseExtractor) {
Assert.notNull(responseExtractor, "responseExtractor must not be null");
- return sendAndReceive(new WebServiceMessageCallback() {
+ return sendAndReceive(uri, new WebServiceMessageCallback() {
public void doInMessage(WebServiceMessage message) throws IOException {
try {
transformer.transform(requestPayload, message.getPayloadResult());
@@ -255,37 +331,40 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService
sendAndReceive(requestCallback, new WebServiceMessageCallbackMessageExtractor(responseCallback));
}
+ public void sendAndReceive(String uri,
+ WebServiceMessageCallback requestCallback,
+ WebServiceMessageCallback responseCallback) {
+ Assert.notNull(responseCallback, "responseCallback must not be null");
+ sendAndReceive(uri, requestCallback, new WebServiceMessageCallbackMessageExtractor(responseCallback));
+ }
+
public Object sendAndReceive(WebServiceMessageCallback requestCallback,
WebServiceMessageExtractor responseExtractor) {
- Assert.notNull(responseExtractor, "response extractor must not be null");
- MessageContext messageContext = createMessageContext();
+ return sendAndReceive(getDefaultUri(), requestCallback, responseExtractor);
+ }
+
+ public Object sendAndReceive(String uri,
+ WebServiceMessageCallback requestCallback,
+ WebServiceMessageExtractor responseExtractor) {
+ Assert.notNull(responseExtractor, "'responseExtractor' must not be null");
+ Assert.hasLength(uri, "'uri' must not be empty");
WebServiceConnection connection = null;
try {
- connection = getMessageSender().createConnection();
- WebServiceMessage request = messageContext.getRequest();
+ connection = createConnection(uri);
+ WebServiceMessage request = getMessageFactory().createWebServiceMessage();
if (requestCallback != null) {
requestCallback.doInMessage(request);
}
- sendRequest(connection, messageContext);
- TransportInputStream tis = connection.getTransportInputStream();
- if (tis != null) {
- try {
- messageContext.readResponse(tis);
- logResponse(messageContext);
- if (messageContext.hasResponse()) {
- WebServiceMessage response = messageContext.getResponse();
- if (!hasFault(connection, messageContext)) {
- // normal response
- return responseExtractor.extractData(response);
- }
- else {
- // fault response
- getFaultResolver().resolveFault(response);
- }
- }
+ sendRequest(connection, request);
+ WebServiceMessage response = receiveResponse(connection);
+ if (response != null) {
+ if (!hasFault(connection, response)) {
+ // normal response
+ return responseExtractor.extractData(response);
}
- finally {
- tis.close();
+ else {
+ // fault response
+ getFaultResolver().resolveFault(response);
}
}
return null;
@@ -309,48 +388,43 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService
}
/** Sends the request in the given message context over the connection. */
- private void sendRequest(WebServiceConnection connection, MessageContext messageContext) throws IOException {
+ private void sendRequest(WebServiceConnection connection, WebServiceMessage request) throws IOException {
if (logger.isTraceEnabled()) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
- messageContext.getRequest().writeTo(os);
+ request.writeTo(os);
logger.trace("WebServiceTemplate sends request [" + os.toString("UTF-8") + "]");
}
else if (logger.isDebugEnabled()) {
- logger.debug("WebServiceTemplate sends request [" + messageContext.getRequest() + "]");
+ logger.debug("WebServiceTemplate sends request [" + request + "]");
}
- TransportOutputStream tos = connection.getTransportOutputStream();
- try {
- messageContext.getRequest().writeTo(tos);
- tos.flush();
+ connection.send(request);
+ }
+
+ private WebServiceMessage receiveResponse(WebServiceConnection connection) throws IOException {
+ WebServiceMessage response = connection.receive(getMessageFactory());
+ if (response != null) {
+ if (logger.isTraceEnabled()) {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ response.writeTo(os);
+ logger.trace("WebServiceTemplate receives response [" + os.toString("UTF-8") + "]");
+ }
+ else if (logger.isDebugEnabled()) {
+ logger.debug("WebServiceTemplate receives response [" + response + "]");
+ }
}
- finally {
- tos.close();
+ else if (logger.isDebugEnabled()) {
+ logger.debug("WebServiceTemplate receives no response");
}
+ return response;
}
/** Determines whether the given connection or message context has a fault. */
- private boolean hasFault(WebServiceConnection connection, MessageContext messageContext) throws IOException {
+ private boolean hasFault(WebServiceConnection connection, WebServiceMessage response) throws IOException {
if (connection instanceof FaultAwareWebServiceConnection) {
return ((FaultAwareWebServiceConnection) connection).hasFault();
}
else {
- return messageContext.getResponse().hasFault();
- }
- }
-
- private void logResponse(MessageContext messageContext) throws IOException {
- if (messageContext.hasResponse()) {
- if (logger.isTraceEnabled()) {
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- messageContext.getResponse().writeTo(os);
- logger.trace("WebServiceTemplate receives response [" + os.toString("UTF-8") + "]");
- }
- else if (logger.isDebugEnabled()) {
- logger.debug("WebServiceTemplate receives response [" + messageContext.getRequest() + "]");
- }
- }
- else if (logger.isDebugEnabled()) {
- logger.debug("WebServiceTemplate receives no response for request [" + messageContext.getRequest() + "]");
+ return response.hasFault();
}
}
diff --git a/core/src/main/java/org/springframework/ws/client/core/support/WebServiceGatewaySupport.java b/core/src/main/java/org/springframework/ws/client/core/support/WebServiceGatewaySupport.java
index 86f0ddf9..c2ecfc0c 100644
--- a/core/src/main/java/org/springframework/ws/client/core/support/WebServiceGatewaySupport.java
+++ b/core/src/main/java/org/springframework/ws/client/core/support/WebServiceGatewaySupport.java
@@ -26,24 +26,19 @@ import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.core.WebServiceTemplate;
-import org.springframework.ws.transport.WebServiceMessageSender;
/**
* Convenient super class for application classes that need Web service access.
*
- * Requires a {@link org.springframework.ws.WebServiceMessageFactory} and {@link org.springframework.ws.transport.WebServiceMessageSender},
- * or a {@link org.springframework.ws.client.core.WebServiceTemplate} instance to be set. It will create its own
- * WebServiceTemplate if WebServiceMessageFactory and WebServiceMessageSender are
- * passed in.
+ * Requires a {@link WebServiceMessageFactory} or a {@link WebServiceTemplate} instance to be set. It will create its
+ * own WebServiceTemplate if WebServiceMessageFactory is passed in.
*
- * 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.core.WebServiceTemplate#marshalSendAndReceive(Object)
- * marshalling methods} of the template are to be used.
+ * In addition to the message factory property, this gateway offers {@link Marshaller} and {@link Unmarshaller}
+ * properties. Setting these is required when the {@link 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.core.WebServiceTemplate
* @see #setMarshaller(org.springframework.oxm.Marshaller)
*/
@@ -63,14 +58,12 @@ public abstract class WebServiceGatewaySupport implements InitializingBean, Appl
}
/**
- * Creates a new WebServiceGatewaySupport instance based on the given message factory and message
- * sender.
+ * Creates a new WebServiceGatewaySupport instance based on the given message factory.
*
* @param messageFactory the message factory to use
- * @param messageSender the message sender to use
*/
- protected WebServiceGatewaySupport(WebServiceMessageFactory messageFactory, WebServiceMessageSender messageSender) {
- webServiceTemplate = new WebServiceTemplate(messageFactory, messageSender);
+ protected WebServiceGatewaySupport(WebServiceMessageFactory messageFactory) {
+ webServiceTemplate = new WebServiceTemplate(messageFactory);
}
/** Returns the WebServiceMessageFactory used by the gateway. */
@@ -83,14 +76,14 @@ public abstract class WebServiceGatewaySupport implements InitializingBean, Appl
webServiceTemplate.setMessageFactory(messageFactory);
}
- /** Returns the WebServiceMessageSender used by the gateway. */
- public final WebServiceMessageSender getMessageSender() {
- return webServiceTemplate.getMessageSender();
+ /** Returns the default URI used by the gateway. */
+ public final String getDefaultUri() {
+ return webServiceTemplate.getDefaultUri();
}
- /** Sets the WebServiceMessageSender to be used by the gateway. */
- public final void setMessageSender(WebServiceMessageSender messageSender) {
- webServiceTemplate.setMessageSender(messageSender);
+ /** Sets the default URI used by the gateway. */
+ public final void setDefaultUri(String uri) {
+ webServiceTemplate.setDefaultUri(uri);
}
/** Returns the WebServiceTemplate for the gateway. */
diff --git a/core/src/main/java/org/springframework/ws/client/support/WebServiceAccessor.java b/core/src/main/java/org/springframework/ws/client/support/WebServiceAccessor.java
index e26c2b9a..b38e58db 100644
--- a/core/src/main/java/org/springframework/ws/client/support/WebServiceAccessor.java
+++ b/core/src/main/java/org/springframework/ws/client/support/WebServiceAccessor.java
@@ -16,17 +16,18 @@
package org.springframework.ws.client.support;
+import java.io.IOException;
+
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import org.springframework.ws.WebServiceMessageFactory;
-import org.springframework.ws.context.DefaultMessageContext;
-import org.springframework.ws.context.MessageContext;
+import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.WebServiceMessageSender;
import org.springframework.xml.transform.TransformerObjectSupport;
/**
* Base class for WebServiceTemplate and other WS-accessing helpers. Defines common properties like the
- * {@link org.springframework.ws.WebServiceMessageFactory} and {@link org.springframework.ws.transport.WebServiceMessageSender}.
+ * {@link WebServiceMessageFactory} and {@link WebServiceMessageSender}.
*
* Not intended to be used directly. See {@link org.springframework.ws.client.core.WebServiceTemplate}.
*
@@ -37,48 +38,58 @@ public abstract class WebServiceAccessor extends TransformerObjectSupport implem
private WebServiceMessageFactory messageFactory;
- private WebServiceMessageSender messageSender;
+ private WebServiceMessageSender[] messageSenders;
- /**
- * Returns the message factory used for creating messages.
- */
+ /** Returns the message factory used for creating messages. */
public WebServiceMessageFactory getMessageFactory() {
return messageFactory;
}
- /**
- * Sets the message factory used for creating messages.
- */
+ /** Sets the message factory used for creating messages. */
public void setMessageFactory(WebServiceMessageFactory messageFactory) {
this.messageFactory = messageFactory;
}
- /**
- * Returns the message sender.
- */
- public WebServiceMessageSender getMessageSender() {
- return messageSender;
+ /** Returns the message senders used for sending messages. */
+ public WebServiceMessageSender[] getMessageSenders() {
+ return messageSenders;
}
- /**
- * Sets the message sender.
- */
public void setMessageSender(WebServiceMessageSender messageSender) {
- this.messageSender = messageSender;
+ Assert.notNull(messageSender, "'messageSender' must not be null");
+ this.messageSenders = new WebServiceMessageSender[]{messageSender};
}
- /**
- * Returns a MessageContext with an empty message, and the defined
- * WebServiceMessageFactory.
- *
- * @return the created message context
- */
- protected MessageContext createMessageContext() {
- return new DefaultMessageContext(getMessageFactory());
+ public void setMessageSenders(WebServiceMessageSender[] messageSenders) {
+ Assert.notEmpty(messageSenders, "'messageSenders' must not be empty");
+ this.messageSenders = messageSenders;
}
public void afterPropertiesSet() throws Exception {
- Assert.notNull(getMessageFactory(), "messageFactory is required");
- Assert.notNull(getMessageSender(), "messageSender is required");
+ Assert.notNull(getMessageFactory(), "Property 'messageFactory' is required");
+ Assert.notEmpty(getMessageSenders(), "Property 'messageSenders' is required");
}
+
+ /**
+ * Creates a connection to the given URI, or throws an exception when it cannot be resolved.
+ *
+ * @param uri the URI to open a connection to
+ * @return the created connection
+ * @throws IllegalArgumentException when the uri cannot be resolved
+ * @throws IOException when an I/O error occurs
+ */
+ protected WebServiceConnection createConnection(String uri) throws IOException {
+ Assert.notEmpty(getMessageSenders(), "Property 'messageSenders' is required");
+ WebServiceMessageSender messageSender = null;
+ WebServiceMessageSender[] messageSenders = getMessageSenders();
+ for (int i = 0; i < messageSenders.length; i++) {
+ if (messageSenders[i].supports(uri)) {
+ messageSender = messageSenders[i];
+ break;
+ }
+ }
+ Assert.notNull(messageSender, "Could not resolve [" + uri + "] to a WebServiceMessageSender");
+ return messageSender.createConnection(uri);
+ }
+
}
diff --git a/core/src/main/java/org/springframework/ws/client/support/package.html b/core/src/main/java/org/springframework/ws/client/support/package.html
new file mode 100644
index 00000000..edee4deb
--- /dev/null
+++ b/core/src/main/java/org/springframework/ws/client/support/package.html
@@ -0,0 +1,6 @@
+
+
+Classes supporting the org.springframework.ws.client.core package.
+Contains a base class for WebServiceTemplate usage.
+
+
\ No newline at end of file
diff --git a/core/src/main/java/org/springframework/ws/transport/AbstractReceivingWebServiceConnection.java b/core/src/main/java/org/springframework/ws/transport/AbstractReceiverConnection.java
similarity index 81%
rename from core/src/main/java/org/springframework/ws/transport/AbstractReceivingWebServiceConnection.java
rename to core/src/main/java/org/springframework/ws/transport/AbstractReceiverConnection.java
index ac067ec4..b8dac276 100644
--- a/core/src/main/java/org/springframework/ws/transport/AbstractReceivingWebServiceConnection.java
+++ b/core/src/main/java/org/springframework/ws/transport/AbstractReceiverConnection.java
@@ -21,32 +21,25 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
/**
- * Abstract base class for {@link org.springframework.ws.transport.WebServiceConnection} implementations used for
- * sending requests.
+ * Abstract base class for {@link WebServiceConnection} implementations used for receiving requests.
*
* @author Arjen Poutsma
*/
-public abstract class AbstractReceivingWebServiceConnection implements WebServiceConnection {
-
- /** Logger available to subclasses. */
- protected final Log logger = LogFactory.getLog(getClass());
+public abstract class AbstractReceiverConnection extends AbstractWebServiceConnection {
private TransportInputStream requestInputStream;
private TransportOutputStream responseOutputStream;
- public final TransportInputStream getTransportInputStream() throws IOException {
+ protected final TransportInputStream createTransportInputStream() throws IOException {
if (requestInputStream == null) {
requestInputStream = new RequestTransportInputStream();
}
return requestInputStream;
}
- public final TransportOutputStream getTransportOutputStream() throws IOException {
+ protected final TransportOutputStream createTransportOutputStream() throws IOException {
if (responseOutputStream == null) {
responseOutputStream = new ResponseTransportOutputStream();
}
@@ -80,9 +73,6 @@ public abstract class AbstractReceivingWebServiceConnection implements WebServic
/** Returns the output stream to write the request to. */
protected abstract OutputStream getResponseOutputStream() throws IOException;
- /** Sends the response. Called when the {@link ResponseTransportOutputStream#close() is closed}. */
- protected abstract void sendResponse() throws IOException;
-
/** Implementation of TransportInputStream for receiving-side connections. */
private class RequestTransportInputStream extends TransportInputStream {
@@ -113,7 +103,6 @@ public abstract class AbstractReceivingWebServiceConnection implements WebServic
public void close() throws IOException {
super.close();
- sendResponse();
}
}
diff --git a/core/src/main/java/org/springframework/ws/transport/AbstractSendingWebServiceConnection.java b/core/src/main/java/org/springframework/ws/transport/AbstractSenderConnection.java
similarity index 83%
rename from core/src/main/java/org/springframework/ws/transport/AbstractSendingWebServiceConnection.java
rename to core/src/main/java/org/springframework/ws/transport/AbstractSenderConnection.java
index e3ab565e..60aea67a 100644
--- a/core/src/main/java/org/springframework/ws/transport/AbstractSendingWebServiceConnection.java
+++ b/core/src/main/java/org/springframework/ws/transport/AbstractSenderConnection.java
@@ -21,31 +21,25 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
/**
* Abstract base class for {@link WebServiceConnection} implementations used for sending requests.
*
* @author Arjen Poutsma
*/
-public abstract class AbstractSendingWebServiceConnection implements WebServiceConnection {
-
- /** Logger available to subclasses. */
- protected final Log logger = LogFactory.getLog(getClass());
+public abstract class AbstractSenderConnection extends AbstractWebServiceConnection {
private TransportOutputStream requestOutputStream;
private TransportInputStream responseInputStream;
- public final TransportOutputStream getTransportOutputStream() throws IOException {
+ protected final TransportOutputStream createTransportOutputStream() throws IOException {
if (requestOutputStream == null) {
requestOutputStream = new RequestTransportOutputStream();
}
return requestOutputStream;
}
- public final TransportInputStream getTransportInputStream() throws IOException {
+ protected final TransportInputStream createTransportInputStream() throws IOException {
if (hasResponse()) {
if (responseInputStream == null) {
responseInputStream = new ResponseTransportInputStream();
@@ -72,9 +66,6 @@ public abstract class AbstractSendingWebServiceConnection implements WebServiceC
/** Returns the output stream to write the request to. */
protected abstract OutputStream getRequestOutputStream() throws IOException;
- /** Sends the request. Called when the {@link RequestTransportOutputStream#close() is closed}. */
- protected abstract void sendRequest() throws IOException;
-
/**
* Returns an iteration over all the header names this request contains. Returns an empty Iterator if
* there areno headers.
@@ -100,11 +91,6 @@ public abstract class AbstractSendingWebServiceConnection implements WebServiceC
protected OutputStream createOutputStream() throws IOException {
return getRequestOutputStream();
}
-
- public void close() throws IOException {
- super.close();
- sendRequest();
- }
}
/** Implementation of {@link TransportInputStream} for client-side HTTP. */
diff --git a/core/src/main/java/org/springframework/ws/transport/AbstractWebServiceConnection.java b/core/src/main/java/org/springframework/ws/transport/AbstractWebServiceConnection.java
new file mode 100644
index 00000000..c67ee052
--- /dev/null
+++ b/core/src/main/java/org/springframework/ws/transport/AbstractWebServiceConnection.java
@@ -0,0 +1,102 @@
+/*
+ * 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;
+
+import java.io.IOException;
+
+import org.springframework.ws.WebServiceMessage;
+import org.springframework.ws.WebServiceMessageFactory;
+
+/**
+ * Abstract base class for {@link WebServiceConnection} implementations.
+ *
+ * @author Arjen Poutsma
+ */
+public abstract class AbstractWebServiceConnection implements WebServiceConnection {
+
+ public final void send(WebServiceMessage message) throws IOException {
+ TransportOutputStream tos = createTransportOutputStream();
+ try {
+ message.writeTo(tos);
+ tos.flush();
+ }
+ finally {
+ tos.close();
+ }
+ onSend(message);
+ }
+
+ public final WebServiceMessage receive(WebServiceMessageFactory messageFactory) throws IOException {
+ TransportInputStream tis = createTransportInputStream();
+ if (tis == null) {
+ return null;
+ }
+ WebServiceMessage message = null;
+ try {
+ message = messageFactory.createWebServiceMessage(tis);
+ }
+ finally {
+ tis.close();
+ }
+ onReceive(message);
+ return message;
+ }
+
+ /**
+ * Returns a TransportOutputStream for the given message. Called from {@link
+ * #send(WebServiceMessage)}.
+ *
+ * @return the output stream
+ * @throws IOException when an I/O exception occurs
+ */
+ protected abstract TransportOutputStream createTransportOutputStream() throws IOException;
+
+ /**
+ * Called when 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 onSend(WebServiceMessage message) throws IOException {
+
+ }
+
+ /**
+ * Returns a TransportInputStream. Called from {@link #receive(WebServiceMessageFactory)}.
+ *
+ * @return the input stream, or null if no response can be read
+ * @throws IOException when an I/O exception occurs
+ */
+ protected abstract TransportInputStream createTransportInputStream() throws IOException;
+
+ /**
+ * Called when the given message has been written to the TransportOutputStream. Called from {@link
+ * #receive(WebServiceMessageFactory)}.
+ *
+ * Default implementation does nothing.
+ *
+ * @param message the message
+ * @throws IOException when an I/O exception occurs
+ */
+ protected void onReceive(WebServiceMessage message) throws IOException {
+
+ }
+
+}
diff --git a/core/src/main/java/org/springframework/ws/transport/EndpointAwareWebServiceConnection.java b/core/src/main/java/org/springframework/ws/transport/EndpointAwareWebServiceConnection.java
new file mode 100644
index 00000000..1337ad7e
--- /dev/null
+++ b/core/src/main/java/org/springframework/ws/transport/EndpointAwareWebServiceConnection.java
@@ -0,0 +1,33 @@
+/*
+ * 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;
+
+import org.springframework.ws.NoEndpointFoundException;
+
+/**
+ * Sub-interface of {@link WebServiceConnection} that is aware of any server-side situations where an endpoint is not
+ * found. Typically, this results in a special error codes.
+ *
+ * @author Arjen Poutsma
+ * @see NoEndpointFoundException
+ */
+public interface EndpointAwareWebServiceConnection extends WebServiceConnection {
+
+ /** Called when an endpoint is not found. */
+ void endpointNotFound();
+
+}
diff --git a/core/src/main/java/org/springframework/ws/transport/WebServiceConnection.java b/core/src/main/java/org/springframework/ws/transport/WebServiceConnection.java
index 12b8baca..7ac0d1ba 100644
--- a/core/src/main/java/org/springframework/ws/transport/WebServiceConnection.java
+++ b/core/src/main/java/org/springframework/ws/transport/WebServiceConnection.java
@@ -19,59 +19,43 @@ package org.springframework.ws.transport;
import java.io.IOException;
import org.springframework.ws.WebServiceMessage;
-import org.springframework.ws.transport.http.HttpServletConnection;
+import org.springframework.ws.WebServiceMessageFactory;
/**
* Represents a point-to-point connection that a client can use for sending {@link WebServiceMessage} objects directly
* to a remote party.
*
* A WebServiceConnection can be obtained using a {@link WebServiceMessageSender}.
- *
- * On the receiving side, the typical usage scenario for this connection is: null if no transport input stream is available (eg. a request might not have a response).
+ * Sends the given message using this connection.
*
- * @return a transport input stream for this connection, or null
- * @throws IOException if an I/O error occurs when creating the input stream, the connection is closed
+ * @param message the message to be sent
+ * @throws IOException in case of I/O errors
*/
- TransportInputStream getTransportInputStream() throws IOException;
+ void send(WebServiceMessage message) throws IOException;
/**
- * Returns a transport output stream for this connection.
- *
- * Returns null if no transport output stream is available (eg. a response might not have a response).
+ * Receives a message using the given {@link WebServiceMessageFactory}. This method blocks until it receives, or
+ * returns null when no message is received.
*
- * @return a transport output stream for this connection
- * @throws IOException if an I/O error occurs when creating the output stream, the connection is closed
+ * @param messageFactory the message factory used for reading messages
+ * @return the read message, or null if no message received
+ * @throws IOException in case of I/O errors
*/
- TransportOutputStream getTransportOutputStream() throws IOException;
+ WebServiceMessage receive(WebServiceMessageFactory messageFactory) throws IOException;
/**
* Closes this connection.
*
* Once a connection has been closed, it is not available for further use. A new connection needs to be created.
*
- * @throws IOException if an I/O error occurs when closing this socket
+ * @throws IOException if an I/O error occurs when closing this connection
*/
void close() throws IOException;
diff --git a/core/src/main/java/org/springframework/ws/transport/WebServiceMessageSender.java b/core/src/main/java/org/springframework/ws/transport/WebServiceMessageSender.java
index 2ce3b174..7a0f8e0c 100644
--- a/core/src/main/java/org/springframework/ws/transport/WebServiceMessageSender.java
+++ b/core/src/main/java/org/springframework/ws/transport/WebServiceMessageSender.java
@@ -2,9 +2,11 @@ package org.springframework.ws.transport;
import java.io.IOException;
+import org.springframework.ws.WebServiceMessage;
+
/**
- * Defines the methods for classes capable of sending and receiving {@link org.springframework.ws.WebServiceMessage}
- * instances across a transport.
+ * Defines the methods for classes capable of sending and receiving {@link WebServiceMessage} instances across a
+ * transport.
*
* The WebServiceMessageSender is basically a factory for {@link WebServiceConnection} objects.
*
@@ -14,11 +16,20 @@ import java.io.IOException;
public interface WebServiceMessageSender {
/**
- * Create a new WebServiceConnection.
+ * Create a new {@link WebServiceConnection} to the specified URI.
*
+ * @param uri the URI to open a connection to
* @return the new connection
* @throws IOException in case of I/O errors
*/
- WebServiceConnection createConnection() throws IOException;
+ WebServiceConnection createConnection(String uri) throws IOException;
+
+ /**
+ * Indicates whether the message sender supports the given URI.
+ *
+ * @param uri the URI
+ * @return true
+ */
+ boolean supports(String uri);
}
diff --git a/core/src/main/java/org/springframework/ws/transport/http/AbstractHttpSendingWebServiceConnection.java b/core/src/main/java/org/springframework/ws/transport/http/AbstractHttpSenderConnection.java
similarity index 94%
rename from core/src/main/java/org/springframework/ws/transport/http/AbstractHttpSendingWebServiceConnection.java
rename to core/src/main/java/org/springframework/ws/transport/http/AbstractHttpSenderConnection.java
index 80059ae3..c5a4984d 100644
--- a/core/src/main/java/org/springframework/ws/transport/http/AbstractHttpSendingWebServiceConnection.java
+++ b/core/src/main/java/org/springframework/ws/transport/http/AbstractHttpSenderConnection.java
@@ -23,7 +23,7 @@ import java.util.Iterator;
import java.util.zip.GZIPInputStream;
import org.springframework.util.FileCopyUtils;
-import org.springframework.ws.transport.AbstractSendingWebServiceConnection;
+import org.springframework.ws.transport.AbstractSenderConnection;
import org.springframework.ws.transport.FaultAwareWebServiceConnection;
import org.springframework.ws.transport.WebServiceConnection;
@@ -32,7 +32,7 @@ import org.springframework.ws.transport.WebServiceConnection;
*
* @author Arjen Poutsma
*/
-public abstract class AbstractHttpSendingWebServiceConnection extends AbstractSendingWebServiceConnection
+public abstract class AbstractHttpSenderConnection extends AbstractSenderConnection
implements FaultAwareWebServiceConnection {
protected static final String HTTP_HEADER_CONTENT_ENCODING = "Content-Encoding";
diff --git a/core/src/main/java/org/springframework/ws/transport/http/AbstractHttpWebServiceMessageSender.java b/core/src/main/java/org/springframework/ws/transport/http/AbstractHttpWebServiceMessageSender.java
index 6f5861b4..e6a86100 100644
--- a/core/src/main/java/org/springframework/ws/transport/http/AbstractHttpWebServiceMessageSender.java
+++ b/core/src/main/java/org/springframework/ws/transport/http/AbstractHttpWebServiceMessageSender.java
@@ -16,10 +16,7 @@
package org.springframework.ws.transport.http;
-import java.net.URL;
-
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.util.Assert;
+import org.springframework.util.StringUtils;
import org.springframework.ws.transport.WebServiceMessageSender;
/**
@@ -28,9 +25,7 @@ import org.springframework.ws.transport.WebServiceMessageSender;
*
* @author Arjen Poutsma
*/
-public abstract class AbstractHttpWebServiceMessageSender implements WebServiceMessageSender, InitializingBean {
-
- private URL url;
+public abstract class AbstractHttpWebServiceMessageSender implements WebServiceMessageSender {
private boolean acceptGzipEncoding = true;
@@ -38,15 +33,9 @@ public abstract class AbstractHttpWebServiceMessageSender implements WebServiceM
protected static final String ENCODING_GZIP = "gzip";
- /** Returns the url used by this message sender. */
- public URL getUrl() {
- return url;
- }
+ protected static final String HTTP_SCHEME = "http://";
- /** Sets the url used by this message sender. */
- public void setUrl(URL url) {
- this.url = url;
- }
+ protected static final String HTTPS_SCHEME = "https://";
/**
* Return whether to accept GZIP encoding, that is, whether to send the HTTP Accept-Encoding header
@@ -67,8 +56,7 @@ public abstract class AbstractHttpWebServiceMessageSender implements WebServiceM
this.acceptGzipEncoding = acceptGzipEncoding;
}
- public void afterPropertiesSet() throws Exception {
- Assert.notNull(url, "url is required");
+ public boolean supports(String uri) {
+ return StringUtils.hasLength(uri) && (uri.startsWith(HTTP_SCHEME) || uri.startsWith(HTTPS_SCHEME));
}
-
}
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 a8377c90..50e1ffa7 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
@@ -29,6 +29,7 @@ import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.springframework.util.Assert;
+import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.transport.WebServiceConnection;
/**
@@ -37,7 +38,7 @@ import org.springframework.ws.transport.WebServiceConnection;
*
* @author Arjen Poutsma
*/
-public class CommonsHttpConnection extends AbstractHttpSendingWebServiceConnection {
+public class CommonsHttpConnection extends AbstractHttpSenderConnection {
private final HttpClient httpClient;
@@ -52,6 +53,10 @@ public class CommonsHttpConnection extends AbstractHttpSendingWebServiceConnecti
this.postMethod = postMethod;
}
+ public PostMethod getPostMethod() {
+ return postMethod;
+ }
+
public void close() throws IOException {
postMethod.releaseConnection();
}
@@ -64,7 +69,7 @@ public class CommonsHttpConnection extends AbstractHttpSendingWebServiceConnecti
return bufferedOutput;
}
- protected void sendRequest() throws IOException {
+ protected void onSend(WebServiceMessage message) throws IOException {
postMethod.setRequestEntity(new ByteArrayRequestEntity(bufferedOutput.toByteArray()));
bufferedOutput = null;
httpClient.executeMethod(postMethod);
diff --git a/core/src/main/java/org/springframework/ws/transport/http/CommonsHttpMessageSender.java b/core/src/main/java/org/springframework/ws/transport/http/CommonsHttpMessageSender.java
index 467da065..fc2ab909 100644
--- a/core/src/main/java/org/springframework/ws/transport/http/CommonsHttpMessageSender.java
+++ b/core/src/main/java/org/springframework/ws/transport/http/CommonsHttpMessageSender.java
@@ -78,8 +78,8 @@ public class CommonsHttpMessageSender extends AbstractHttpWebServiceMessageSende
this.httpClient = httpClient;
}
- public WebServiceConnection createConnection() throws IOException {
- PostMethod postMethod = new PostMethod(getUrl().toString());
+ public WebServiceConnection createConnection(String uri) throws IOException {
+ PostMethod postMethod = new PostMethod(uri);
if (isAcceptGzipEncoding()) {
postMethod.addRequestHeader(HTTP_HEADER_ACCEPT_ENCODING, ENCODING_GZIP);
}
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 152820ee..a223a65f 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
@@ -23,7 +23,9 @@ import java.util.Iterator;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.springframework.ws.transport.AbstractReceivingWebServiceConnection;
+import org.springframework.ws.WebServiceMessage;
+import org.springframework.ws.transport.AbstractReceiverConnection;
+import org.springframework.ws.transport.EndpointAwareWebServiceConnection;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.support.EnumerationIterator;
@@ -32,57 +34,73 @@ import org.springframework.ws.transport.support.EnumerationIterator;
*
* @author Arjen Poutsma
*/
-public class HttpServletConnection extends AbstractReceivingWebServiceConnection {
+public class HttpServletConnection extends AbstractReceiverConnection implements EndpointAwareWebServiceConnection {
- private final HttpServletRequest request;
+ private final HttpServletRequest httpServletRequest;
- private final HttpServletResponse response;
+ private final HttpServletResponse httpServletResponse;
+
+ private boolean sentResponse = false;
+
+ private boolean endpointFound = true;
/**
* Constructs a new servlet connection with the given HttpServletRequest and
* HttpServletResponse.
*/
public HttpServletConnection(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
- request = httpServletRequest;
- response = httpServletResponse;
+ this.httpServletRequest = httpServletRequest;
+ 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 request;
+ return httpServletRequest;
}
/** Returns the HttpServletResponse for this connection. */
public HttpServletResponse getHttpServletResponse() {
- return response;
+ return httpServletResponse;
+ }
+
+ public void endpointNotFound() {
+ endpointFound = false;
+ httpServletResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
}
protected Iterator getRequestHeaderNames() throws IOException {
- return new EnumerationIterator(request.getHeaderNames());
+ return new EnumerationIterator(httpServletRequest.getHeaderNames());
}
protected Iterator getRequestHeaders(String name) throws IOException {
- return new EnumerationIterator(request.getHeaders(name));
+ return new EnumerationIterator(httpServletRequest.getHeaders(name));
}
protected InputStream getRequestInputStream() throws IOException {
- return request.getInputStream();
+ return httpServletRequest.getInputStream();
}
protected void addResponseHeader(String name, String value) throws IOException {
- response.addHeader(name, value);
+ httpServletResponse.addHeader(name, value);
}
protected OutputStream getResponseOutputStream() throws IOException {
- return response.getOutputStream();
+ return httpServletResponse.getOutputStream();
}
- protected void sendResponse() throws IOException {
- // no op
+ protected void onSend(WebServiceMessage message) throws IOException {
+ sentResponse = true;
+ if (!message.hasFault()) {
+ httpServletResponse.setStatus(HttpServletResponse.SC_OK);
+ }
+ else {
+ httpServletResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ }
}
-
- public void close() throws IOException {
- // no op
- }
-
}
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 d0e5a7a1..ae26bc19 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
@@ -28,6 +28,7 @@ import java.util.Set;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
+import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.transport.WebServiceConnection;
/**
@@ -35,7 +36,7 @@ import org.springframework.ws.transport.WebServiceConnection;
*
* @author Arjen Poutsma
*/
-public class HttpUrlConnection extends AbstractHttpSendingWebServiceConnection {
+public class HttpUrlConnection extends AbstractHttpSenderConnection {
private final HttpURLConnection connection;
@@ -49,6 +50,10 @@ public class HttpUrlConnection extends AbstractHttpSendingWebServiceConnection {
this.connection = connection;
}
+ public HttpURLConnection getConnection() {
+ return connection;
+ }
+
public void close() {
connection.disconnect();
}
@@ -61,7 +66,7 @@ public class HttpUrlConnection extends AbstractHttpSendingWebServiceConnection {
return connection.getOutputStream();
}
- protected void sendRequest() throws IOException {
+ protected void onSend(WebServiceMessage message) throws IOException {
connection.connect();
}
@@ -111,5 +116,4 @@ public class HttpUrlConnection extends AbstractHttpSendingWebServiceConnection {
connection.getResponseCode() + ", status message = [" + connection.getResponseMessage() + "]");
}
}
-
}
diff --git a/core/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionMessageSender.java b/core/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionMessageSender.java
index 347c3054..bd87664a 100644
--- a/core/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionMessageSender.java
+++ b/core/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionMessageSender.java
@@ -18,6 +18,7 @@ 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.transport.WebServiceConnection;
@@ -27,8 +28,8 @@ import org.springframework.ws.transport.WebServiceConnection;
* without support for HTTP authentication or advanced configuration options.
*
* Designed for easy subclassing, customizing specific template methods. However, consider {@link
- * org.springframework.ws.transport.http.CommonsHttpMessageSender} for more sophisticated needs: the J2SE
- * HttpURLConnection is rather limited in its capabilities.
+ * CommonsHttpMessageSender} for more sophisticated needs: the J2SE HttpURLConnection is rather limited in
+ * its capabilities.
*
* @author Arjen Poutsma
* @see java.net.HttpURLConnection
@@ -37,10 +38,11 @@ public class HttpUrlConnectionMessageSender extends AbstractHttpWebServiceMessag
private static final String HTTP_METHOD_POST = "POST";
- public WebServiceConnection createConnection() throws IOException {
- URLConnection connection = getUrl().openConnection();
+ public WebServiceConnection createConnection(String uri) throws IOException {
+ URL url = new URL(uri);
+ URLConnection connection = url.openConnection();
if (!(connection instanceof HttpURLConnection)) {
- throw new HttpTransportException("URL [" + getUrl() + "] is not an HTTP URL");
+ throw new HttpTransportException("URI [" + uri + "] is not an HTTP URL");
}
else {
HttpURLConnection httpURLConnection = (HttpURLConnection) connection;
diff --git a/core/src/main/java/org/springframework/ws/transport/http/WebServiceMessageReceiverHandlerAdapter.java b/core/src/main/java/org/springframework/ws/transport/http/WebServiceMessageReceiverHandlerAdapter.java
index e0ae2366..820c9c5e 100644
--- a/core/src/main/java/org/springframework/ws/transport/http/WebServiceMessageReceiverHandlerAdapter.java
+++ b/core/src/main/java/org/springframework/ws/transport/http/WebServiceMessageReceiverHandlerAdapter.java
@@ -21,7 +21,6 @@ import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.ModelAndView;
-import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.WebServiceMessageReceiver;
import org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport;
@@ -67,30 +66,4 @@ public class WebServiceMessageReceiverHandlerAdapter extends WebServiceMessageRe
return handler instanceof WebServiceMessageReceiver;
}
- /** Sets the response code to 204, Accepted. */
- protected void handleNoResponse(WebServiceConnection connection) {
- HttpServletResponse httpServletResponse = ((HttpServletConnection) connection).getHttpServletResponse();
- httpServletResponse.setStatus(HttpServletResponse.SC_ACCEPTED);
- }
-
- /**
- * Sets the response code to 200, OK, for normal responses. Set the code to 500, Internal Server Error, in case of a
- * SOAP Fault,
- */
- protected void handleResponse(WebServiceConnection connection, WebServiceMessage response) throws Exception {
- HttpServletResponse httpServletResponse = ((HttpServletConnection) connection).getHttpServletResponse();
- if (response.hasFault()) {
- httpServletResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- }
- else {
- httpServletResponse.setStatus(HttpServletResponse.SC_OK);
- }
- super.handleResponse(connection, response);
- }
-
- /** Sets the response code to 404, Not Found. */
- protected void handleNoEndpointFound(WebServiceConnection connection) {
- HttpServletResponse httpServletResponse = ((HttpServletConnection) connection).getHttpServletResponse();
- httpServletResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
- }
}
diff --git a/core/src/main/java/org/springframework/ws/transport/support/WebServiceMessageReceiverObjectSupport.java b/core/src/main/java/org/springframework/ws/transport/support/WebServiceMessageReceiverObjectSupport.java
index f2c4cb7e..1c646ed2 100644
--- a/core/src/main/java/org/springframework/ws/transport/support/WebServiceMessageReceiverObjectSupport.java
+++ b/core/src/main/java/org/springframework/ws/transport/support/WebServiceMessageReceiverObjectSupport.java
@@ -27,8 +27,7 @@ import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
-import org.springframework.ws.transport.TransportInputStream;
-import org.springframework.ws.transport.TransportOutputStream;
+import org.springframework.ws.transport.EndpointAwareWebServiceConnection;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.WebServiceMessageReceiver;
import org.springframework.ws.transport.context.DefaultTransportContext;
@@ -80,17 +79,17 @@ public abstract class WebServiceMessageReceiverObjectSupport implements Initiali
TransportContextHolder.setTransportContext(new DefaultTransportContext(connection));
try {
- MessageContext messageContext = handleRequest(connection);
+ WebServiceMessage request = connection.receive(getMessageFactory());
+ MessageContext messageContext = new DefaultMessageContext(request, getMessageFactory());
receiver.receive(messageContext);
- if (!messageContext.hasResponse()) {
- handleNoResponse(connection);
- }
- else {
- handleResponse(connection, messageContext.getResponse());
+ if (messageContext.hasResponse()) {
+ connection.send(request);
}
}
catch (NoEndpointFoundException ex) {
- handleNoEndpointFound(connection);
+ if (connection instanceof EndpointAwareWebServiceConnection) {
+ ((EndpointAwareWebServiceConnection) connection).endpointNotFound();
+ }
}
finally {
try {
@@ -103,53 +102,4 @@ public abstract class WebServiceMessageReceiverObjectSupport implements Initiali
}
}
- private MessageContext handleRequest(WebServiceConnection connection) throws IOException {
- TransportInputStream tis = connection.getTransportInputStream();
- try {
- WebServiceMessage messageRequest = getMessageFactory().createWebServiceMessage(tis);
- return new DefaultMessageContext(messageRequest, getMessageFactory());
- }
- finally {
- tis.close();
- }
- }
-
- /**
- * Invoked from {@link #handleConnection} when no response is given. Default implementation does nothing. Can be
- * overriden to set certain transport-specific response headers.
- *
- * @param connection the incoming connection
- */
- protected void handleNoResponse(WebServiceConnection connection) {
- }
-
- /**
- * Handles the sending of the response. Invoked from {@link #handleConnection}. Default implementation writes the
- * given response to the given TransportOutputStream. Can be overriden to set certain
- * transport-specific headers.
- *
- * @param connection the incoming connection
- * @param response the response message
- * @see WebServiceMessage#writeTo(java.io.OutputStream)
- */
- protected void handleResponse(WebServiceConnection connection, WebServiceMessage response) throws Exception {
- TransportOutputStream tos = connection.getTransportOutputStream();
- try {
- response.writeTo(tos);
- tos.flush();
- }
- finally {
- tos.close();
- }
- }
-
- /**
- * Invoked from {@link #handleConnection} when no suitable endpoint is found. Default implementation does nothing.
- * Can be overriden to set certain transport-specific response headers.
- *
- * @param connection the incoming connection
- */
- protected void handleNoEndpointFound(WebServiceConnection connection) {
- }
-
}
diff --git a/core/src/main/java/org/springframework/ws/transport/support/package.html b/core/src/main/java/org/springframework/ws/transport/support/package.html
new file mode 100644
index 00000000..7b03a3fe
--- /dev/null
+++ b/core/src/main/java/org/springframework/ws/transport/support/package.html
@@ -0,0 +1,5 @@
+
+
+Classes supporting the org.springframework.ws.transport package.
+
+
\ No newline at end of file
diff --git a/core/src/main/resources/org/springframework/ws/client/core/WebServiceTemplate.properties b/core/src/main/resources/org/springframework/ws/client/core/WebServiceTemplate.properties
index 2b4a00a6..539831b6 100644
--- a/core/src/main/resources/org/springframework/ws/client/core/WebServiceTemplate.properties
+++ b/core/src/main/resources/org/springframework/ws/client/core/WebServiceTemplate.properties
@@ -1,4 +1,5 @@
# Default implementation classes for WebServiceTemplate's strategy interfaces.
# Not meant to be customized by application developers.
-org.springframework.ws.WebServiceMessageFactory=org.springframework.ws.soap.saaj.SaajSoapMessageFactory
\ No newline at end of file
+org.springframework.ws.WebServiceMessageFactory=org.springframework.ws.soap.saaj.SaajSoapMessageFactory
+org.springframework.ws.transport.WebServiceMessageSender=org.springframework.ws.transport.http.HttpUrlConnectionMessageSender
\ No newline at end of file
diff --git a/core/src/test/java/org/springframework/ws/client/core/SimpleSaajServlet.java b/core/src/test/java/org/springframework/ws/client/core/SimpleSaajServlet.java
index c4057aa1..13bd7f77 100644
--- a/core/src/test/java/org/springframework/ws/client/core/SimpleSaajServlet.java
+++ b/core/src/test/java/org/springframework/ws/client/core/SimpleSaajServlet.java
@@ -99,15 +99,18 @@ public class SimpleSaajServlet extends HttpServlet {
MimeHeaders headers = getHeaders(req);
SOAPMessage msg = msgFactory.createMessage(headers, req.getInputStream());
SOAPMessage reply = onMessage(msg);
- resp.setStatus(HttpServletResponse.SC_OK);
if (reply != null) {
if (reply.saveRequired()) {
reply.saveChanges();
}
- resp.setStatus(HttpServletResponse.SC_OK);
+ resp.setStatus(!reply.getSOAPBody().hasFault() ? HttpServletResponse.SC_OK :
+ HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
putHeaders(reply.getMimeHeaders(), resp);
reply.writeTo(resp.getOutputStream());
}
+ else {
+ resp.setStatus(HttpServletResponse.SC_ACCEPTED);
+ }
}
catch (Exception ex) {
throw new ServletException("SAAJ POST failed " + ex.getMessage());
diff --git a/core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateIntegrationTest.java b/core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateIntegrationTest.java
index 95fef487..09d16df4 100644
--- a/core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateIntegrationTest.java
+++ b/core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateIntegrationTest.java
@@ -16,7 +16,6 @@
package org.springframework.ws.client.core;
-import java.net.URL;
import javax.xml.soap.MessageFactory;
import org.custommonkey.xmlunit.XMLTestCase;
@@ -40,9 +39,8 @@ public class WebServiceTemplateIntegrationTest extends XMLTestCase {
jettyContext.addServlet(SimpleSaajServlet.class, "/");
jettyServer.start();
template = new WebServiceTemplate();
- HttpUrlConnectionMessageSender messageSender = new HttpUrlConnectionMessageSender();
- messageSender.setUrl(new URL("http://localhost:8888/"));
- template.setMessageSender(messageSender);
+ template.setDefaultUri("http://localhost:8888/");
+ template.setMessageSender(new HttpUrlConnectionMessageSender());
}
protected void tearDown() throws Exception {
diff --git a/core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateTest.java b/core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateTest.java
index 88bbdf38..9523c743 100644
--- a/core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateTest.java
+++ b/core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateTest.java
@@ -16,19 +16,16 @@
package org.springframework.ws.client.core;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.custommonkey.xmlunit.XMLTestCase;
import org.easymock.MockControl;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
+import org.springframework.ws.MockWebServiceMessage;
import org.springframework.ws.MockWebServiceMessageFactory;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.transport.FaultAwareWebServiceConnection;
-import org.springframework.ws.transport.MockTransportInputStream;
-import org.springframework.ws.transport.MockTransportOutputStream;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.WebServiceMessageSender;
import org.springframework.xml.transform.StringResult;
@@ -42,19 +39,29 @@ public class WebServiceTemplateTest extends XMLTestCase {
private FaultAwareWebServiceConnection connectionMock;
+ private MockWebServiceMessageFactory messageFactory;
+
+ private static final String URI = "uri";
+
protected void setUp() throws Exception {
template = new WebServiceTemplate();
- MockWebServiceMessageFactory messageFactory = new MockWebServiceMessageFactory();
+ messageFactory = new MockWebServiceMessageFactory();
template.setMessageFactory(messageFactory);
connectionControl = MockControl.createStrictControl(FaultAwareWebServiceConnection.class);
connectionMock = (FaultAwareWebServiceConnection) connectionControl.getMock();
template.setMessageSender(new WebServiceMessageSender() {
- public WebServiceConnection createConnection() throws IOException {
+ public WebServiceConnection createConnection(String uri) throws IOException {
return connectionMock;
}
+
+ public boolean supports(String uri) {
+ assertEquals("Invalid uri", URI, uri);
+ return true;
+ }
});
+ template.setDefaultUri(URI);
}
public void testMarshalAndSendNoMarshallerSet() throws Exception {
@@ -94,10 +101,10 @@ public class WebServiceTemplateTest extends XMLTestCase {
extractorControl.setReturnValue(extracted);
extractorControl.replay();
- connectionControl.expectAndReturn(connectionMock.getTransportOutputStream(),
- new MockTransportOutputStream(new ByteArrayOutputStream()));
- connectionControl.expectAndReturn(connectionMock.getTransportInputStream(),
- new MockTransportInputStream(new ByteArrayInputStream("