Added Tcp/IP transport.

This commit is contained in:
Arjen Poutsma
2007-04-11 11:48:01 +00:00
parent ef258debfa
commit 84fce85a69
28 changed files with 1622 additions and 21 deletions

View File

@@ -56,6 +56,12 @@
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jmx</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<!-- JEE dependencies -->
<dependency>
<groupId>javax.xml.soap</groupId>

View File

@@ -17,6 +17,7 @@
package org.springframework.ws.server.endpoint.adapter;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
import javax.xml.namespace.QName;
@@ -104,14 +105,24 @@ public class XPathParamAnnotationEndpointAdapter extends AbstractMethodEndpointA
}
protected void invokeInternal(MessageContext messageContext, MethodEndpoint methodEndpoint) throws Exception {
Element payloadElement = getMessagePayloadElement(messageContext.getRequest());
Object[] args = getMethodArguments(payloadElement, methodEndpoint.getMethod());
Object result = methodEndpoint.invoke(args);
if (result != null && result instanceof Source) {
Source responseSource = (Source) result;
WebServiceMessage response = messageContext.getResponse();
Transformer transformer = createTransformer();
transformer.transform(responseSource, response.getPayloadResult());
try {
Element payloadElement = getMessagePayloadElement(messageContext.getRequest());
Object[] args = getMethodArguments(payloadElement, methodEndpoint.getMethod());
Object result = methodEndpoint.invoke(args);
if (result != null && result instanceof Source) {
Source responseSource = (Source) result;
WebServiceMessage response = messageContext.getResponse();
Transformer transformer = createTransformer();
transformer.transform(responseSource, response.getPayloadResult());
}
}
catch (InvocationTargetException ex) {
if (ex.getTargetException() instanceof Exception) {
throw (Exception) ex.getTargetException();
}
else {
throw ex;
}
}
}

View File

@@ -1,5 +0,0 @@
<html>
<body>
Provides miscellaneous endpoints <code>EndpointAdapter</code> implementations.
</body>
</html>

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.server.endpoint.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.ws.server.endpoint.mapping.AbstractAnnotationEndpointMapping;
import org.springframework.ws.soap.server.endpoint.mapping.SoapActionAnnotationEndpointMapping;
/**
* Marks a class as an endpoint.
* <p/>
* Instances of this class are typically picked up by an {@link AbstractAnnotationEndpointMapping} implementation, such
* as {@link SoapActionAnnotationEndpointMapping}.
*
* @author Arjen Poutsma
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Endpoint {
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.server.endpoint.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PayloadRootQName {
String value();
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.server.endpoint.mapping;
import java.lang.annotation.Annotation;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
/**
* Abstract base for {@link org.springframework.ws.server.EndpointMapping} implementations that map classes tagged with
* an annotation. By default the annotation is {@link Endpoint}, but this can be overriden in subclasses.
* <p/>
* Each bean
*
* @author Arjen Poutsma
*/
public abstract class AbstractAnnotationEndpointMapping extends AbstractMethodEndpointMapping
implements BeanPostProcessor {
public final Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
registerMethods(bean);
return bean;
}
/** Returns the 'endpoint' annotation type. Default is {@link Endpoint}. */
protected Class<? extends Annotation> getEndpointAnnotationType() {
return Endpoint.class;
}
public final Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}

View File

@@ -0,0 +1,150 @@
/*
* Copyright 2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.server.endpoint.mapping;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContextException;
import org.springframework.core.JdkVersion;
import org.springframework.util.StringUtils;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.server.endpoint.MethodEndpoint;
/**
* Abstract base class for {@link MethodEndpoint} mappings.
* <p/>
* Subclasses typically implement {@link org.springframework.beans.factory.config.BeanPostProcessor} to look for beans
* that qualify as enpoint. The methods of this bean are then registered under a specific key with {@link
* #registerEndpoint(String,MethodEndpoint)}.
*
* @author Arjen Poutsma
*/
public abstract class AbstractMethodEndpointMapping extends AbstractEndpointMapping {
/** Keys are Strings, values are {@link MethodEndpoint}s. */
private final Map endpointMap = new HashMap();
/**
* Lookup an endpoint for the given message. The extraction of the endpoint key is delegated to the concrete
* subclass.
*
* @return the looked up endpoint, or <code>null</code>
* @see #getLookupKeyForMessage(MessageContext)
*/
protected Object getEndpointInternal(MessageContext messageContext) throws Exception {
String key = getLookupKeyForMessage(messageContext);
if (!StringUtils.hasLength(key)) {
return null;
}
if (logger.isDebugEnabled()) {
logger.debug("Looking up endpoint for [" + key + "]");
}
return lookupEndpoint(key);
}
/**
* Returns the the endpoint keys for the given message context.
*
* @return the registration keys
*/
protected abstract String getLookupKeyForMessage(MessageContext messageContext) throws Exception;
/**
* Looks up an endpoint instance for the given keys. All keys are tried in order.
*
* @param key key the beans are mapped to
* @return the associated endpoint instance, or <code>null</code> if not found
*/
protected MethodEndpoint lookupEndpoint(String key) {
return (MethodEndpoint) endpointMap.get(key);
}
/**
* Register the given endpoint instance under the key.
*
* @param key the lookup key
* @param endpoint the method endpoint instance
* @throws BeansException if the endpoint could not be registered
*/
protected void registerEndpoint(String key, MethodEndpoint endpoint) throws BeansException {
Object mappedEndpoint = endpointMap.get(key);
if (mappedEndpoint != null) {
throw new ApplicationContextException("Cannot map endpoint [" + endpoint + "] on registration key [" + key +
"]: there's already endpoint [" + mappedEndpoint + "] mapped");
}
if (endpoint == null) {
throw new ApplicationContextException("Could not find endpoint for key [" + key + "]");
}
endpointMap.put(key, endpoint);
if (logger.isDebugEnabled()) {
logger.debug("Mapped key [" + key + "] onto endpoint [" + endpoint + "]");
}
}
/**
* Helper method that registers the methods of the given bean. This method iterates over the methods of the bean,
* and calls {@link #getLookupKeyForMethod(Method)} for each. If this returns a string, the method is registered
* using {@link #registerEndpoint(String,MethodEndpoint)}.
*
* @see #getLookupKeyForMethod(Method)
*/
protected void registerMethods(Object endpoint) {
Method[] methods = getEndpointClass(endpoint).getMethods();
for (int i = 0; i < methods.length; i++) {
if (JdkVersion.isAtLeastJava15() && methods[i].isSynthetic() ||
methods[i].getDeclaringClass().equals(Object.class)) {
continue;
}
String key = getLookupKeyForMethod(methods[i]);
if (StringUtils.hasLength(key)) {
registerEndpoint(key, new MethodEndpoint(endpoint, methods[i]));
}
}
}
/**
* Returns the the endpoint keys for the given method. Returns <code>null</code> if the method is not to be
* registered, which is the default.
*
* @param method the method
* @return a registration key, or <code>null</code> if the method is not to be registered
*/
protected String getLookupKeyForMethod(Method method) {
return null;
}
/**
* Return the class or interface to use for method reflection.
* <p/>
* Default implementation returns the target class for a CGLIB proxy, and the class of the given bean else (for a
* JDK proxy or a plain bean class).
*
* @param endpoint the bean instance (might be an AOP proxy)
* @return the bean class to expose
*/
protected Class getEndpointClass(Object endpoint) {
if (AopUtils.isCglibProxy(endpoint)) {
return endpoint.getClass().getSuperclass();
}
return endpoint.getClass();
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright 2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.server.endpoint.mapping;
import java.lang.reflect.Method;
import javax.xml.namespace.QName;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.server.endpoint.annotation.PayloadRootQName;
import org.springframework.xml.namespace.QNameUtils;
import org.w3c.dom.Element;
/** @author Arjen Poutsma */
public class PayloadRootQNameMethodEndpointMapping extends AbstractAnnotationEndpointMapping {
private static TransformerFactory transformerFactory;
static {
transformerFactory = TransformerFactory.newInstance();
}
protected String getLookupKeyForMessage(MessageContext messageContext) throws Exception {
Element payloadElement = getMessagePayloadElement(messageContext.getRequest());
QName qName = QNameUtils.getQNameForNode(payloadElement);
return qName != null ? qName.toString() : null;
}
protected String getLookupKeyForMethod(Method method) {
PayloadRootQName annotation = AnnotationUtils.getAnnotation(method, PayloadRootQName.class);
return annotation != null ? annotation.value() : null;
}
private Element getMessagePayloadElement(WebServiceMessage message) throws TransformerException {
Transformer transformer = transformerFactory.newTransformer();
DOMResult domResult = new DOMResult();
transformer.transform(message.getPayloadSource(), domResult);
return (Element) domResult.getNode().getFirstChild();
}
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright 2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.server.endpoint.mapping;
import java.lang.reflect.Method;
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.dom.DOMSource;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.context.MessageContext;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* Simple subclass of {@link AbstractMethodEndpointMapping} that maps to all methods that start with a prefix, and end
* with a suffix. Endpoint beans are registered using the <code>endpoints</code> property.
*
* @author Arjen Poutsma
*/
public class SimpleMethodEndpointMapping extends AbstractMethodEndpointMapping implements InitializingBean {
public static final String DEFAULT_METHOD_PREFIX = "handle";
public static final String DEFAULT_METHOD_SUFFIX = "";
private Object[] endpoints;
private String methodPrefix = DEFAULT_METHOD_PREFIX;
private String methodSuffix = DEFAULT_METHOD_SUFFIX;
private TransformerFactory transformerFactory;
/** Sets the endpoints */
public void setEndpoints(Object[] endpoints) {
this.endpoints = endpoints;
}
/**
* Sets the method prefix. All methods with names starting with this string will be registered. Default is
* "<code>handle</code>".
*
* @see #DEFAULT_METHOD_PREFIX
*/
public void setMethodPrefix(String methodPrefix) {
this.methodPrefix = methodPrefix;
}
/**
* Sets the method suffix. All methods with names ending with this string will be registered. Default is "" (i.e. no
* suffix).
*
* @see #DEFAULT_METHOD_SUFFIX
*/
public void setMethodSuffix(String methodSuffix) {
this.methodSuffix = methodSuffix;
}
public void afterPropertiesSet() throws Exception {
Assert.notEmpty(endpoints, "endpoints is required");
transformerFactory = TransformerFactory.newInstance();
for (int i = 0; i < endpoints.length; i++) {
registerMethods(endpoints[i]);
}
}
/** Returns the name of the given method, with the prefix and suffix stripped off. */
protected String getLookupKeyForMethod(Method method) {
String methodName = method.getName();
if (methodName.startsWith(methodPrefix) && methodName.endsWith(methodSuffix)) {
return methodName.substring(methodPrefix.length(), methodName.length() - methodSuffix.length());
}
else {
return null;
}
}
protected String getLookupKeyForMessage(MessageContext messageContext) throws TransformerException {
Element payloadElement = getMessagePayloadElement(messageContext.getRequest());
return payloadElement.getLocalName();
}
private Element getMessagePayloadElement(WebServiceMessage message) throws TransformerException {
if (message.getPayloadSource() instanceof DOMSource) {
DOMSource domSource = (DOMSource) message.getPayloadSource();
if (domSource.getNode().getNodeType() == Node.ELEMENT_NODE) {
return (Element) domSource.getNode();
}
}
Transformer transformer = transformerFactory.newTransformer();
DOMResult domResult = new DOMResult();
transformer.transform(message.getPayloadSource(), domResult);
return (Element) domResult.getNode().getFirstChild();
}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap.server.endpoint.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** @author Arjen Poutsma */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SoapAction {
String value();
}

View File

@@ -0,0 +1,107 @@
/*
* 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.soap.server.endpoint.mapping;
import java.lang.reflect.Method;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.server.EndpointInterceptor;
import org.springframework.ws.server.EndpointInvocationChain;
import org.springframework.ws.server.endpoint.mapping.AbstractAnnotationEndpointMapping;
import org.springframework.ws.soap.SoapEndpointMapping;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.server.SoapEndpointInvocationChain;
import org.springframework.ws.soap.server.endpoint.annotation.SoapAction;
/**
* Implementation of the <code>EndpointMapping</code> interface to map from <code>SOAPAction</code> headers to endpoint
* beans. Supports both mapping to bean instances and mapping to bean names: the latter is required for prototype
* handlers.
* <p/>
* The <code>endpointMap</code> property is suitable for populating the endpoint map with bean references, e.g. via the
* map element in XML bean definitions.
* <p/>
* Mappings to bean names can be set via the <code>mappings</code> property, in a form accepted by the
* <code>java.util.Properties</code> class, like as follows:
* <pre>
* http://www.springframework.org/spring-ws/samples/airline/BookFlight=bookFlightEndpoint
* http://www.springframework.org/spring-ws/samples/airline/GetFlights=getFlightsEndpoint
* </pre>
* The syntax is SOAP_ACTION=ENDPOINT_BEAN_NAME.
* <p/>
* This endpoint mapping does not read from the request message, and therefore is more suitable for message contexts
* which directly read from the transport request (such as the <code>AxiomSoapMessageContextFactory</code> with the
* <code>payloadCaching</code> disabled).
*
* @author Arjen Poutsma
*/
public class SoapActionAnnotationEndpointMapping extends AbstractAnnotationEndpointMapping
implements SoapEndpointMapping {
private String[] actorsOrRoles;
public final void setActorOrRole(String actorOrRole) {
Assert.notNull(actorOrRole, "actorOrRole must not be null");
actorsOrRoles = new String[]{actorOrRole};
}
public final void setActorsOrRoles(String[] actorsOrRoles) {
Assert.notEmpty(actorsOrRoles, "actorsOrRoles must not be empty");
this.actorsOrRoles = actorsOrRoles;
}
/**
* Creates a new <code>SoapEndpointInvocationChain</code> based on the given endpoint, and the set interceptors, and
* actors/roles.
*
* @param endpoint the endpoint
* @param interceptors the endpoint interceptors
* @return the created invocation chain
* @see #setInterceptors(org.springframework.ws.server.EndpointInterceptor[])
* @see #setActorsOrRoles(String[])
*/
protected final EndpointInvocationChain createEndpointInvocationChain(MessageContext messageContext,
Object endpoint,
EndpointInterceptor[] interceptors) {
return new SoapEndpointInvocationChain(endpoint, interceptors, actorsOrRoles);
}
protected String getLookupKeyForMessage(MessageContext messageContext) throws Exception {
if (messageContext.getRequest() instanceof SoapMessage) {
SoapMessage request = (SoapMessage) messageContext.getRequest();
String soapAction = request.getSoapAction();
if (StringUtils.hasLength(soapAction) && soapAction.charAt(0) == '"' &&
soapAction.charAt(soapAction.length() - 1) == '"') {
return soapAction.substring(1, soapAction.length() - 1);
}
else {
return soapAction;
}
}
else {
return null;
}
}
protected String getLookupKeyForMethod(Method method) {
SoapAction soapAction = AnnotationUtils.getAnnotation(method, SoapAction.class);
return soapAction != null ? soapAction.value() : null;
}
}

View File

@@ -17,6 +17,7 @@
package org.springframework.ws.transport.jms;
import java.io.IOException;
import javax.jms.BytesMessage;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
@@ -30,7 +31,15 @@ import org.springframework.util.Assert;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.WebServiceMessageSender;
/** @author Arjen Poutsma */
/**
* <code>WebServiceMessageSender</code> implementation that uses JMS {@link Queue}.
* <p/>
* This message sender sends the request message of the queue configured with either the <code>queue</code> or
* <code>queueName</code> property. It creates a temporary queue for the response message. For both request and response
* {@link BytesMessage}s are used.
*
* @author Arjen Poutsma
*/
public class JmsMessageSender implements WebServiceMessageSender {
/** Default timeout for receive operations. */

View File

@@ -30,7 +30,8 @@ import org.springframework.ws.transport.WebServiceMessageReceiver;
* Spring-2.0 {@link SessionAwareMessageListener} that can be used to handleMessage incoming JMS messages. Requires a
* {@link WebServiceMessageFactory} which is used to convert the incoming JMS {@link BytesMessage}s into a {@link
* WebServiceMessage}, and passes that context to the {@link WebServiceMessageReceiver} set with the property
* <code>messageReceiver</code>. If a response is created, it is sent using a response JMS message.
* <code>messageReceiver</code>. If a response is created, it is sent using the {@link BytesMessage#getJMSReplyTo()
* reply to header} of the request message.
*
* @author Arjen Poutsma
* @see #setMessageFactory(org.springframework.ws.WebServiceMessageFactory)

View File

@@ -0,0 +1,38 @@
/*
* 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.mail;
import javax.jms.JMSException;
import javax.mail.MessagingException;
import org.springframework.ws.transport.TransportException;
/** @author Arjen Poutsma */
public class MailTransportException extends TransportException {
public MailTransportException(String msg) {
super(msg);
}
public MailTransportException(String msg, JMSException ex) {
super(msg + ": " + ex.getMessage());
}
public MailTransportException(MessagingException ex) {
super(ex.getMessage());
}
}

View File

@@ -23,9 +23,7 @@ import javax.mail.MessagingException;
import org.springframework.ws.transport.TransportOutputStream;
/**
* @author Arjen Poutsma
*/
/** @author Arjen Poutsma */
public class MailTransportOutputStream extends TransportOutputStream {
private final Message message;
@@ -51,4 +49,5 @@ public class MailTransportOutputStream extends TransportOutputStream {
throw new IOException(ex.getMessage());
}
}
}

View File

@@ -0,0 +1,171 @@
/*
* 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.support;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.Lifecycle;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.util.ClassUtils;
/**
* Abstract base class for standalone, server-side transport objects. Contains a Spring {@link TaskExecutor}, and
* various lifecycle callbacks.
*
* @author Arjen Poutsma
*/
public abstract class AbstractMessagingContainer extends SimpleWebServiceMessageReceiverObjectSupport
implements Lifecycle, DisposableBean, BeanNameAware {
/** Default thread name prefix. */
public final String DEFAULT_THREAD_NAME_PREFIX = ClassUtils.getShortName(getClass()) + "-";
private volatile boolean active = false;
private boolean autoStartup = true;
private boolean running = false;
private final Object lifecycleMonitor = new Object();
private TaskExecutor taskExecutor;
private String beanName;
/**
* Set whether to automatically start the listener after initialization.
* <p/>
* Default is <code>true</code>; set this to <code>false</code> to allow for manual startup.
*/
public void setAutoStartup(boolean autoStartup) {
this.autoStartup = autoStartup;
}
/**
* Set the Spring {@link TaskExecutor} to use for running the listener threads. Default is {@link
* SimpleAsyncTaskExecutor}, starting up a number of new threads.
* <p/>
* Specify an alternative task executor for integration with an existing thread pool, such as the {@link
* org.springframework.scheduling.commonj.WorkManagerTaskExecutor} to integrate with WebSphere or WebLogic.
*/
public void setTaskExecutor(TaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
/** Returns the task executor. */
public TaskExecutor getTaskExecutor() {
return taskExecutor;
}
public void setBeanName(String beanName) {
this.beanName = beanName;
}
/** Return whether this server is currently active, that is, whether it has been set up but not shut down yet. */
public final boolean isActive() {
synchronized (lifecycleMonitor) {
return active;
}
}
/** Return whether this server is currently running, that is, whether it has been started and not stopped yet. */
public final boolean isRunning() {
synchronized (lifecycleMonitor) {
return running;
}
}
/**
* Create a default TaskExecutor. Called if no explicit TaskExecutor has been specified.
* <p/>
* The default implementation builds a {@link org.springframework.core.task.SimpleAsyncTaskExecutor} with the
* specified bean name (or the class name, if no bean name specified) as thread name prefix.
*
* @see org.springframework.core.task.SimpleAsyncTaskExecutor#SimpleAsyncTaskExecutor(String)
*/
protected TaskExecutor createDefaultTaskExecutor() {
String threadNamePrefix = beanName != null ? beanName + "-" : DEFAULT_THREAD_NAME_PREFIX;
return new SimpleAsyncTaskExecutor(threadNamePrefix);
}
public void afterPropertiesSet() throws Exception {
super.afterPropertiesSet();
if (taskExecutor == null) {
taskExecutor = createDefaultTaskExecutor();
}
activate();
}
/**
* Calls <code>shutdown</code> when the BeanFactory destroys the server instance.
*
* @see #shutdown()
*/
public void destroy() {
shutdown();
}
/** Initialize this server. Starts the server if <code>autoStartup</code> hasn't been turned off. */
public final void activate() throws Exception {
synchronized (lifecycleMonitor) {
active = true;
lifecycleMonitor.notifyAll();
}
onActivate();
if (autoStartup) {
start();
}
}
/** Start this server. */
public final void start() {
synchronized (lifecycleMonitor) {
running = true;
lifecycleMonitor.notifyAll();
}
onStart();
}
/** Stop this server. */
public final void stop() {
synchronized (lifecycleMonitor) {
running = false;
lifecycleMonitor.notifyAll();
}
onStop();
}
/** Shut down the registered listeners and close this listener container. */
public final void shutdown() {
synchronized (lifecycleMonitor) {
running = false;
active = false;
lifecycleMonitor.notifyAll();
}
onShutdown();
}
protected abstract void onActivate() throws Exception;
protected abstract void onStart();
protected abstract void onStop();
protected abstract void onShutdown();
}

View File

@@ -0,0 +1,73 @@
/*
* 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.tcp;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.WebServiceMessageSender;
/** @author Arjen Poutsma */
public class TcpMessageSender implements WebServiceMessageSender, InitializingBean {
private InetAddress address;
private int port = -1;
private int timeOut = 1000;
/** Sets the port the sender will connect to. */
public void setPort(int port) {
this.port = port;
}
/** Sets the amount of milliseconds before the tcp connection will timeout. */
public void setTimeOut(int timeOut) {
this.timeOut = timeOut;
}
/**
* Sets the internet address the client will connect to.
*
* @throws java.net.UnknownHostException when the given address is not known
*/
public void setAddress(String address) throws UnknownHostException {
this.address = InetAddress.getByName(address);
}
public WebServiceConnection createConnection() throws IOException {
Socket socket = new Socket();
SocketAddress socketAddress = new InetSocketAddress(address, port);
socket.connect(socketAddress, timeOut);
return new TcpSendingWebServiceConnection(socket);
}
public void afterPropertiesSet() throws Exception {
if (port == -1) {
throw new IllegalArgumentException("port is required");
}
Assert.notNull(address, "address is required");
}
}

View File

@@ -0,0 +1,167 @@
/*
* 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.tcp;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.support.AbstractMessagingContainer;
/** @author Arjen Poutsma */
public class TcpMessagingContainer extends AbstractMessagingContainer {
private ServerSocket serverSocket;
private InetAddress bindAddress;
private int backlog = -1;
private int port = -1;
/** Sets the port the server will bind to. */
public void setPort(int port) {
this.port = port;
}
/** Sets the server back log. */
public void setBacklog(int backlog) {
this.backlog = backlog;
}
/**
* Sets the local internet address the server will bind to. By default, it will accept connections on any/all local
* addresses.
*
* @throws java.net.UnknownHostException when the given address is not known
* @see java.net.ServerSocket#ServerSocket(int,int,java.net.InetAddress)
*/
public void setBindAddress(String bindAddress) throws UnknownHostException {
this.bindAddress = InetAddress.getByName(bindAddress);
}
public void afterPropertiesSet() throws Exception {
super.afterPropertiesSet();
if (port == -1) {
throw new IllegalArgumentException("port is required");
}
openServerSocket();
}
protected void onActivate() throws IOException {
openServerSocket();
}
protected void onStart() {
if (logger.isInfoEnabled()) {
logger.info("Starting tcp server [" + serverSocket.getLocalSocketAddress() + "]");
}
getTaskExecutor().execute(new SocketAcceptingRunnable());
}
protected void onStop() {
if (logger.isInfoEnabled()) {
logger.info("Stopping tcp server [" + serverSocket.getLocalSocketAddress() + "]");
}
}
protected void onShutdown() {
if (logger.isInfoEnabled()) {
logger.info("Shutting down tcp server [" + serverSocket.getLocalSocketAddress() + "]");
}
closeServerSocket();
}
/**
* Establish a shared <code>ServerSocket</code> for this server.
* <p/>
* The default implementation delegates to <code>refreshSharedConnection</code>, which does one immediate attempt
* and throws an exception if it fails. Can be overridden to have a recovery proces in place, retrying until a
* ServerSocket can be successfully established.
*
* @see #refreshServerSocket()
*/
protected void openServerSocket() throws IOException {
refreshServerSocket();
}
/**
* Refresh the shared <code>ServerSocket</code> that this server holds.
* <p/>
* Called on startup and also after an infrastructure exception that occured during listener setup and/or
* execution.
*/
protected final void refreshServerSocket() throws IOException {
closeServerSocket();
serverSocket = new ServerSocket(port, backlog, bindAddress);
}
protected void closeServerSocket() {
if (serverSocket == null) {
return;
}
try {
serverSocket.close();
}
catch (IOException ex) {
logger.debug("Could not close ServerSocket", ex);
}
}
private class SocketAcceptingRunnable implements Runnable {
public void run() {
while (isRunning()) {
try {
Socket socket = serverSocket.accept();
TcpRequestHandler handler = new TcpRequestHandler(socket);
getTaskExecutor().execute(handler);
}
catch (InterruptedIOException ex) {
logger.warn(ex);
}
catch (IOException ex) {
logger.warn("Could not accept incoming connection: " + ex.getMessage());
}
}
}
}
private class TcpRequestHandler implements Runnable {
private final Socket socket;
public TcpRequestHandler(Socket socket) {
this.socket = socket;
}
public void run() {
WebServiceConnection connection = new TcpReceivingWebServiceConnection(socket);
try {
handleConnection(connection);
}
catch (Exception ex) {
logger.warn("Could not handle request", ex);
}
}
}
}

View File

@@ -0,0 +1,80 @@
/*
* 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.tcp;
import java.io.FilterInputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Collections;
import java.util.Iterator;
import org.springframework.util.Assert;
import org.springframework.ws.transport.AbstractReceivingWebServiceConnection;
/** @author Arjen Poutsma */
public class TcpReceivingWebServiceConnection extends AbstractReceivingWebServiceConnection {
private final Socket socket;
public TcpReceivingWebServiceConnection(Socket socket) {
Assert.notNull(socket, "socket must not be null");
this.socket = socket;
}
public void close() throws IOException {
socket.close();
}
protected Iterator getRequestHeaderNames() throws IOException {
return Collections.EMPTY_LIST.iterator();
}
protected Iterator getRequestHeaders(String name) throws IOException {
return Collections.EMPTY_LIST.iterator();
}
protected InputStream getRequestInputStream() throws IOException {
return new FilterInputStream(socket.getInputStream()) {
public void close() throws IOException {
// don't close the socket
socket.shutdownInput();
}
};
}
protected void addResponseHeader(String name, String value) throws IOException {
}
protected OutputStream getResponseOutputStream() throws IOException {
return new FilterOutputStream(socket.getOutputStream()) {
public void close() throws IOException {
// don't close the socket
socket.shutdownOutput();
}
};
}
protected void sendResponse() throws IOException {
}
}

View File

@@ -0,0 +1,82 @@
/*
* 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.tcp;
import java.io.FilterInputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Collections;
import java.util.Iterator;
import org.springframework.util.Assert;
import org.springframework.ws.transport.AbstractSendingWebServiceConnection;
/** @author Arjen Poutsma */
public class TcpSendingWebServiceConnection extends AbstractSendingWebServiceConnection {
private final Socket socket;
public TcpSendingWebServiceConnection(Socket socket) {
Assert.notNull(socket, "socket must not be null");
this.socket = socket;
}
public void close() throws IOException {
socket.close();
}
protected void addRequestHeader(String name, String value) throws IOException {
}
protected OutputStream getRequestOutputStream() throws IOException {
return new FilterOutputStream(socket.getOutputStream()) {
public void close() throws IOException {
// don't close the socket
socket.shutdownOutput();
}
};
}
protected void sendRequest() throws IOException {
}
protected boolean hasResponse() throws IOException {
return true;
}
protected Iterator getResponseHeaderNames() throws IOException {
return Collections.EMPTY_LIST.iterator();
}
protected Iterator getResponseHeaders(String name) throws IOException {
return Collections.EMPTY_LIST.iterator();
}
protected InputStream getResponseInputStream() throws IOException {
return new FilterInputStream(socket.getInputStream()) {
public void close() throws IOException {
// don't close the socket
socket.shutdownInput();
}
};
}
}

View File

@@ -0,0 +1,37 @@
/*
* 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.tcp;
import java.io.IOException;
import org.springframework.ws.transport.TransportException;
/** @author Arjen Poutsma */
public class TcpTransportException extends TransportException {
public TcpTransportException(String msg) {
super(msg);
}
public TcpTransportException(String msg, IOException ex) {
super(msg + ": " + ex.getMessage());
}
public TcpTransportException(IOException ex) {
super(ex.getMessage());
}
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright 2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.server.endpoint.mapping;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import junit.framework.TestCase;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.server.endpoint.MethodEndpoint;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
/** TestCase for {@link AbstractAnnotationEndpointMapping} */
public class AnnotationEndpointMappingTest extends TestCase {
private AbstractAnnotationEndpointMapping mapping;
private StaticApplicationContext applicationContext;
protected void setUp() throws Exception {
applicationContext = new StaticApplicationContext();
applicationContext.registerSingleton("mapping", MyAnnotationEndpointMapping.class);
applicationContext.registerSingleton("endpoint", MyEndpoint.class);
applicationContext.registerSingleton("other", OtherBean.class);
applicationContext.refresh();
mapping = (AbstractAnnotationEndpointMapping) applicationContext.getBean("mapping");
}
public void testRegistration() throws NoSuchMethodException {
MethodEndpoint endpoint = mapping.lookupEndpoint("arg");
assertNotNull("MethodEndpoint not registered", endpoint);
MethodEndpoint expected = new MethodEndpoint(applicationContext.getBean("endpoint"), "doIt", new Class[0]);
assertEquals("Invalid endpoint registered", expected, endpoint);
assertNull("Invalid endpoint registered", mapping.lookupEndpoint("arg2"));
}
private static class MyAnnotationEndpointMapping extends AbstractAnnotationEndpointMapping {
protected String getLookupKeyForMethod(Method method) {
MyAnnotation annotation = AnnotationUtils.getAnnotation(method, MyAnnotation.class);
if (annotation != null) {
return annotation.value();
}
else {
return null;
}
}
protected String getLookupKeyForMessage(MessageContext messageContext) throws Exception {
return "arg";
}
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value();
}
@Endpoint
private static class MyEndpoint {
@MyAnnotation("arg")
public void doIt() {
}
}
private static class OtherBean {
@MyAnnotation("arg2")
public void doIt() {
}
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.server.endpoint.mapping;
import junit.framework.TestCase;
import org.springframework.ws.MockWebServiceMessage;
import org.springframework.ws.MockWebServiceMessageFactory;
import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
public class SimpleMethodEndpointMappingTest extends TestCase {
private SimpleMethodEndpointMapping mapping;
protected void setUp() throws Exception {
mapping = new SimpleMethodEndpointMapping();
mapping.setMethodPrefix("prefix");
mapping.setMethodSuffix("Suffix");
MyBean bean = new MyBean();
mapping.setEndpoints(new Object[]{bean});
mapping.afterPropertiesSet();
}
public void testRegistration() throws Exception {
assertNotNull("Endpoint not registered", mapping.lookupEndpoint("MyRequest"));
}
public void testGetLookupKeyForMessageNoNamespace() throws Exception {
MockWebServiceMessage request = new MockWebServiceMessage("<MyRequest/>");
MessageContext messageContext = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
String result = mapping.getLookupKeyForMessage(messageContext);
assertEquals("Invalid lookup key", "MyRequest", result);
}
public void testGetLookupKeyForMessageNamespace() throws Exception {
MockWebServiceMessage request =
new MockWebServiceMessage("<MyRequest xmlns='http://springframework.org/spring-ws/' />");
MessageContext messageContext = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
String result = mapping.getLookupKeyForMessage(messageContext);
assertEquals("Invalid lookup key", "MyRequest", result);
}
private static class MyBean {
public void prefixMyRequestSuffix() {
}
public void request() {
}
}
}

View File

@@ -0,0 +1,50 @@
/*
* 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.soap.server.endpoint.mapping;
import junit.framework.TestCase;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.soap.server.endpoint.annotation.SoapAction;
public class SoapActionAnnotationEndpointMappingTest extends TestCase {
private StaticApplicationContext applicationContext;
private SoapActionAnnotationEndpointMapping mapping;
protected void setUp() throws Exception {
applicationContext = new StaticApplicationContext();
applicationContext.registerSingleton("mapping", SoapActionAnnotationEndpointMapping.class);
applicationContext.registerSingleton("endpoint", MyEndpoint.class);
applicationContext.refresh();
mapping = (SoapActionAnnotationEndpointMapping) applicationContext.getBean("mapping");
}
public void testIt() {
}
@Endpoint
private static class MyEndpoint {
@SoapAction("http://springframework.org/spring-ws/action")
public void handleMessage() {
}
}
}

View File

@@ -14,19 +14,19 @@
* limitations under the License.
*/
package org.springframework.ws.transport.jms;
package org.springframework.ws.transport;
import javax.xml.transform.Transformer;
import junit.framework.Assert;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.transport.WebServiceMessageReceiver;
import org.springframework.xml.transform.TransformerObjectSupport;
public class SimpleTestingMessageReceiver extends TransformerObjectSupport implements WebServiceMessageReceiver {
public void receive(MessageContext messageContext) throws Exception {
Assert.assertNotNull("MessageContext is null", messageContext);
logger.info("Received message");
Transformer transformer = createTransformer();
transformer.transform(messageContext.getRequest().getPayloadSource(),
messageContext.getResponse().getPayloadResult());

View File

@@ -0,0 +1,85 @@
/*
* 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.tcp;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket;
import javax.xml.transform.stream.StreamResult;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.transport.WebServiceMessageSender;
import org.springframework.xml.transform.StringSource;
public class TcpServerIntegrationTest extends AbstractDependencyInjectionSpringContextTests {
private WebServiceMessageFactory messageFactory;
private WebServiceMessageSender messageSender;
public void setMessageFactory(WebServiceMessageFactory messageFactory) {
this.messageFactory = messageFactory;
}
public void setMessageSender(WebServiceMessageSender messageSender) {
this.messageSender = messageSender;
}
public static final String REQUEST =
"<SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'\n" +
" SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>\n" +
" <SOAP-ENV:Body>\n" +
" <m:GetLastTradePrice xmlns:m='http://www.springframework.org/spring-ws'>\n" +
" <symbol>DIS</symbol>\n" + " </m:GetLastTradePrice>\n" +
" </SOAP-ENV:Body>\n" + "</SOAP-ENV:Envelope>";
public void testServer() throws IOException, InterruptedException {
Socket socket = new Socket("localhost", 9999);
Writer writer = null;
BufferedReader reader = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"));
writer.write(REQUEST);
writer.flush();
socket.shutdownOutput();
reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
finally {
socket.close();
}
}
public void testTemplate() throws Exception {
WebServiceTemplate template = new WebServiceTemplate(messageFactory, messageSender);
template.sendAndReceive(new StringSource(REQUEST), new StreamResult(System.out));
}
protected String[] getConfigLocations() {
return new String[]{"classpath:/org/springframework/ws/transport/tcp/applicationContext.xml"};
}
}

View File

@@ -28,7 +28,7 @@
<property name="messageReceiver" ref="messageReceiver"/>
</bean>
<bean id="messageReceiver" class="org.springframework.ws.transport.jms.SimpleTestingMessageReceiver"/>
<bean id="messageReceiver" class="org.springframework.ws.transport.SimpleTestingMessageReceiver"/>
</beans>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="messagingContainer" class="org.springframework.ws.transport.tcp.TcpMessagingContainer">
<property name="port" value="9999"/>
<property name="bindAddress" value="localhost"/>
<property name="messageFactory" ref="messageFactory"/>
<property name="messageReceiver">
<bean class="org.springframework.ws.transport.SimpleTestingMessageReceiver"/>
</property>
</bean>
<bean id="tcpSender" class="org.springframework.ws.transport.tcp.TcpMessageSender">
<property name="port" value="9999"/>
<property name="address" value="localhost"/>
</bean>
<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
<!-- define an MBeanExporter -->
<bean id="mbeanExporter" class="org.springframework.jmx.export.MBeanExporter">
<!-- the beans to be exported to JMX -->
<property name="beans">
<map>
<entry key="spring-ws:service=messagingContainer">
<ref local="messagingContainer"/>
</entry>
</map>
</property>
<property name="assembler">
<bean class="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler">
<property name="interfaceMappings">
<props>
<prop key="spring-ws:service=messagingContainer">org.springframework.context.Lifecycle</prop>
</props>
</property>
</bean>
</property>
</bean>
</beans>