Added support module, initialy containing JMS transport

This commit is contained in:
Arjen Poutsma
2007-11-10 17:41:09 +00:00
parent 0c8f81dc86
commit 78cd869765
27 changed files with 2117 additions and 6 deletions

12
pom.xml
View File

@@ -1,5 +1,5 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws</artifactId>
@@ -103,9 +103,10 @@
<module>xml</module>
<module>oxm</module>
<module>core</module>
<module>support</module>
<module>security</module>
<module>archetype</module>
</modules>
</modules>
<profiles>
<profile>
<id>jdk1.5</id>
@@ -250,8 +251,7 @@
<include name="**/*.jpg"/>
</fileset>
</copy>
<move file="target/site/reference/pdf/index.pdf"
tofile="target/site/reference/pdf/spring-ws-reference.pdf" failonerror="false"/>
<move file="target/site/reference/pdf/index.pdf" tofile="target/site/reference/pdf/spring-ws-reference.pdf" failonerror="false"/>
</postProcess>
</configuration>
</plugin>
@@ -733,4 +733,4 @@
<scope>test</scope>
</dependency>
</dependencies>
</project>
</project>

99
support/pom.xml Normal file
View File

@@ -0,0 +1,99 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>spring-ws</artifactId>
<groupId>org.springframework.ws</groupId>
<version>1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-support</artifactId>
<packaging>jar</packaging>
<name>Spring WS Support</name>
<description>Spring Web Services Support package.</description>
<reporting>
<plugins>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<stylesheetfile>${basedir}/../src/main/javadoc/javadoc.css</stylesheetfile>
</configuration>
</plugin>
</plugins>
</reporting>
<profiles>
<profile>
<id>spring-2.0</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-mock</artifactId>
</dependency>
</dependencies>
</profile>
<profile>
<id>spring-2.5</id>
<activation>
<property>
<name>spring.version</name>
<value>2.5-rc1</value>
</property>
</activation>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
</dependencies>
</profile>
</profiles>
<dependencies>
<!-- Spring-WS dependencies -->
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-core</artifactId>
</dependency>
<!-- Spring dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-remoting</artifactId>
<optional>true</optional>
</dependency>
<!-- Java EE dependencies -->
<dependency>
<groupId>javax.xml.soap</groupId>
<artifactId>saaj-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.ejb</groupId>
<artifactId>ejb</artifactId>
<version>2.1</version>
<optional>true</optional>
</dependency>
<!-- Other dependencies -->
<dependency>
<groupId>com.sun.xml.messaging.saaj</groupId>
<artifactId>saaj-impl</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core</artifactId>
<version>4.1.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

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.jms;
import java.io.IOException;
import java.io.InputStream;
import javax.jms.BytesMessage;
import javax.jms.JMSException;
import javax.jms.MessageEOFException;
/**
* Input stream that wraps a {@link BytesMessage}.
*
* @author Arjen Poutsma
* @since 1.1.0
*/
class BytesMessageInputStream extends InputStream {
private BytesMessage message;
BytesMessageInputStream(BytesMessage message) {
this.message = message;
}
public int read(byte b[]) throws IOException {
try {
return message.readBytes(b);
}
catch (JMSException ex) {
throw new JmsTransportException(ex);
}
}
public int read(byte b[], int off, int len) throws IOException {
if (off == 0) {
try {
return message.readBytes(b, len);
}
catch (JMSException ex) {
throw new JmsTransportException(ex);
}
}
else {
return super.read(b, off, len);
}
}
public int read() throws IOException {
try {
return message.readByte();
}
catch (MessageEOFException ex) {
return -1;
}
catch (JMSException ex) {
throw new JmsTransportException(ex);
}
}
}

View File

@@ -0,0 +1,64 @@
/*
* 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.jms;
import java.io.IOException;
import java.io.OutputStream;
import javax.jms.BytesMessage;
import javax.jms.JMSException;
/**
* Output stream that wraps a {@link BytesMessage}.
*
* @author Arjen Poutsma
* @since 1.1.0
*/
class BytesMessageOutputStream extends OutputStream {
private BytesMessage message;
BytesMessageOutputStream(BytesMessage message) {
this.message = message;
}
public void write(byte b[]) throws IOException {
try {
message.writeBytes(b);
}
catch (JMSException ex) {
throw new JmsTransportException(ex);
}
}
public void write(byte b[], int off, int len) throws IOException {
try {
message.writeBytes(b, off, len);
}
catch (JMSException ex) {
throw new JmsTransportException(ex);
}
}
public void write(int b) throws IOException {
try {
message.writeByte((byte) b);
}
catch (JMSException ex) {
throw new JmsTransportException(ex);
}
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2006 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.jms;
import javax.jms.BytesMessage;
import javax.jms.Message;
import javax.jms.Session;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.WebServiceMessageReceiver;
import org.springframework.ws.transport.support.SimpleWebServiceMessageReceiverObjectSupport;
/**
* Convenience base class for JMS server-side transport objects. Contains a {@link WebServiceMessageReceiver}, and has
* methods for handling incoming JMS {@link Message} requests.
* <p/>
* Used by {@link WebServiceMessageListener} and {@link WebServiceMessageDrivenBean}.
*
* @author Arjen Poutsma
* @since 1.1.0
*/
public class JmsMessageReceiver extends SimpleWebServiceMessageReceiverObjectSupport {
/**
* Handles an incoming messages. Uses the given session to create a response message.
*
* @param request the incoming message
* @param session the JMS session used to create a response
* @throws IllegalArgumentException when request is not a {@link BytesMessage}
*/
protected final void handleMessage(Message request, Session session) throws Exception {
if (request instanceof BytesMessage) {
WebServiceConnection connection = new JmsReceiverConnection((BytesMessage) request, session);
handleConnection(connection);
}
else {
throw new IllegalArgumentException(
"Wrong message type: [" + request.getClass() + "]. Only BytesMessages can be handled.");
}
}
}

View File

@@ -0,0 +1,100 @@
/*
* 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.jms;
import java.io.IOException;
import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import org.springframework.jms.support.destination.DestinationResolver;
import org.springframework.jms.support.destination.DynamicDestinationResolver;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.WebServiceMessageSender;
/**
* {@link WebServiceMessageSender} implementation that uses JMS.
* <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
* @since 1.1.0
*/
public class JmsMessageSender implements WebServiceMessageSender, JmsTransportConstants {
/**
* Default timeout for receive operations: -1 indicates a blocking receive without timeout.
*/
public static final long DEFAULT_RECEIVE_TIMEOUT = -1;
private ConnectionFactory connectionFactory;
private DestinationResolver destinationResolver = new DynamicDestinationResolver();
private long receiveTimeout = DEFAULT_RECEIVE_TIMEOUT;
public JmsMessageSender() {
}
public JmsMessageSender(ConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
/**
* Set the ConnectionFactory to use for obtaining JMS {@link Connection}s.
*/
public void setConnectionFactory(ConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
public void setDestinationResolver(DestinationResolver destinationResolver) {
this.destinationResolver = destinationResolver;
}
/**
* Set the timeout to use for receive calls. The default is 0, which means no timeout.
*/
public void setReceiveTimeout(long receiveTimeout) {
this.receiveTimeout = receiveTimeout;
}
public WebServiceConnection createConnection(String uriString) throws IOException {
Assert.notNull(connectionFactory, "connectionFactory must not be null");
JmsSenderConnection connection = null;
try {
JmsUri uri = new JmsUri(uriString);
connection = new JmsSenderConnection(uri, connectionFactory, destinationResolver, receiveTimeout);
return connection;
}
catch (JMSException ex) {
if (connection != null) {
connection.close();
}
throw new JmsTransportException(ex);
}
}
public boolean supports(String uri) {
return StringUtils.hasLength(uri) && uri.startsWith(URI_SCHEME + ":");
}
}

View File

@@ -0,0 +1,202 @@
/*
* 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.jms;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import javax.jms.BytesMessage;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import org.springframework.jms.support.JmsUtils;
import org.springframework.util.Assert;
import org.springframework.ws.FaultAwareWebServiceMessage;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.transport.AbstractReceiverConnection;
import org.springframework.ws.transport.FaultAwareWebServiceConnection;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.jms.support.JmsTransportUtils;
/**
* Implementation of {@link WebServiceConnection} that is used for server-side JMS access.
*
* @author Arjen Poutsma
* @since 1.1.0
*/
public class JmsReceiverConnection extends AbstractReceiverConnection
implements JmsTransportConstants, FaultAwareWebServiceConnection {
private final BytesMessage requestMessage;
private final Session session;
private BytesMessage responseMessage;
/**
* Constructs a new JMS connection with the given parameters.
*/
protected JmsReceiverConnection(BytesMessage requestMessage, Session session) {
Assert.notNull(requestMessage, "requestMessage must not be null");
Assert.notNull(session, "session must not be null");
this.requestMessage = requestMessage;
this.session = session;
}
/**
* Returns the request message for this connection.
*/
public BytesMessage getRequestMessage() {
return requestMessage;
}
/**
* Returns the response message, if any, for this connection.
*/
public BytesMessage getResponseMessage() {
return responseMessage;
}
public String getErrorMessage() throws IOException {
return null;
}
public boolean hasError() throws IOException {
return false;
}
/*
* Receiving
*/
protected Iterator getRequestHeaderNames() throws IOException {
try {
Enumeration headers = requestMessage.getPropertyNames();
List results = new ArrayList();
while (headers.hasMoreElements()) {
String header = (String) headers.nextElement();
if (header.startsWith(JmsTransportConstants.PROPERTY_PREFIX)) {
results.add(header);
}
}
return results.iterator();
}
catch (JMSException ex) {
throw new JmsTransportException("Could not get property names", ex);
}
}
protected Iterator getRequestHeaders(String name) throws IOException {
try {
String value = requestMessage.getStringProperty(name);
return Collections.singletonList(value).iterator();
}
catch (JMSException ex) {
throw new JmsTransportException("Could not get property value", ex);
}
}
protected InputStream getRequestInputStream() throws IOException {
return new BytesMessageInputStream(requestMessage);
}
/*
* Sending
*/
protected void onSendBeforeWrite(WebServiceMessage message) throws IOException {
try {
responseMessage = session.createBytesMessage();
responseMessage.setJMSCorrelationID(requestMessage.getJMSMessageID());
responseMessage.setStringProperty(PROPERTY_BINDING_VERSION, "1.0");
if (message instanceof FaultAwareWebServiceMessage) {
FaultAwareWebServiceMessage faultMessage = (FaultAwareWebServiceMessage) message;
responseMessage.setBooleanProperty(PROPERTY_IS_FAULT, faultMessage.hasFault());
}
}
catch (JMSException ex) {
throw new JmsTransportException("Could not create response message", ex);
}
}
protected void addResponseHeader(String name, String value) throws IOException {
try {
String property = JmsTransportUtils.headerToJmsProperty(name);
responseMessage.setStringProperty(property, value);
}
catch (JMSException ex) {
throw new JmsTransportException("Could not set property", ex);
}
}
protected OutputStream getResponseOutputStream() throws IOException {
return new BytesMessageOutputStream(responseMessage);
}
protected void onSendAfterWrite(WebServiceMessage message) throws IOException {
MessageProducer messageProducer = null;
try {
if (requestMessage.getJMSReplyTo() != null) {
messageProducer = session.createProducer(requestMessage.getJMSReplyTo());
messageProducer.setDeliveryMode(requestMessage.getJMSDeliveryMode());
messageProducer.setPriority(requestMessage.getJMSPriority());
messageProducer.send(responseMessage);
}
}
catch (JMSException ex) {
throw new JmsTransportException(ex);
}
finally {
JmsUtils.closeMessageProducer(messageProducer);
}
}
public void close() throws IOException {
}
/*
* Faults
*/
public boolean hasFault() throws IOException {
try {
return requestMessage.getBooleanProperty(JmsTransportConstants.PROPERTY_IS_FAULT);
}
catch (JMSException ex) {
throw new JmsTransportException(ex);
}
}
public void setFault(boolean fault) throws IOException {
if (responseMessage != null) {
try {
responseMessage.setBooleanProperty(JmsTransportConstants.PROPERTY_IS_FAULT, fault);
}
catch (JMSException ex) {
throw new JmsTransportException(ex);
}
}
}
}

View File

@@ -0,0 +1,276 @@
/*
* 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.jms;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TemporaryQueue;
import org.springframework.jms.connection.ConnectionFactoryUtils;
import org.springframework.jms.support.JmsUtils;
import org.springframework.jms.support.destination.DestinationResolver;
import org.springframework.util.Assert;
import org.springframework.ws.FaultAwareWebServiceMessage;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.transport.AbstractSenderConnection;
import org.springframework.ws.transport.FaultAwareWebServiceConnection;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.jms.support.JmsTransportUtils;
/**
* Implementation of {@link WebServiceConnection} that is used for client-side JMS access.
*
* @author Arjen Poutsma
* @since 1.1.0
*/
public class JmsSenderConnection extends AbstractSenderConnection
implements FaultAwareWebServiceConnection, JmsTransportConstants {
private final ConnectionFactory connectionFactory;
private final DestinationResolver destinationResolver;
private final Connection connection;
private final Session session;
private final Destination requestDestination;
private final JmsUri uri;
private final long receiveTimeout;
private Destination responseDestination;
private BytesMessage requestMessage;
private BytesMessage responseMessage;
/**
* Constructs a new JMS connection with the given parameters.
*/
protected JmsSenderConnection(JmsUri uri,
ConnectionFactory connectionFactory,
DestinationResolver destinationResolver,
long receiveTimeout) throws JMSException {
Assert.notNull(uri, "'uri' must not be null");
Assert.notNull(connectionFactory, "'connectionFactory' must not be null");
Assert.notNull(destinationResolver, "destinationResolver must not be null");
this.connectionFactory = connectionFactory;
this.destinationResolver = destinationResolver;
connection = connectionFactory.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
requestDestination =
destinationResolver.resolveDestinationName(session, uri.getDestination(), uri.isPubSubDomain());
this.uri = uri;
this.receiveTimeout = receiveTimeout;
}
/**
* Returns the request message for this connection.
*/
public BytesMessage getRequestMessage() {
return requestMessage;
}
/**
* Returns the response message, if any, for this connection.
*/
public BytesMessage getResponseMessage() {
return responseMessage;
}
public boolean hasError() throws IOException {
return false;
}
public String getErrorMessage() throws IOException {
return null;
}
/*
* Sending
*/
protected void onSendBeforeWrite(WebServiceMessage message) throws IOException {
try {
requestMessage = session.createBytesMessage();
requestMessage.setStringProperty(PROPERTY_BINDING_VERSION, "1.0");
if (message instanceof FaultAwareWebServiceMessage) {
FaultAwareWebServiceMessage faultMessage = (FaultAwareWebServiceMessage) message;
requestMessage.setBooleanProperty(PROPERTY_IS_FAULT, faultMessage.hasFault());
}
requestMessage.setStringProperty(PROPERTY_REQUEST_IRI, uri.toString());
}
catch (JMSException ex) {
throw new JmsTransportException(ex);
}
}
protected void addRequestHeader(String name, String value) throws IOException {
try {
String property = JmsTransportUtils.headerToJmsProperty(name);
requestMessage.setStringProperty(property, value);
}
catch (JMSException ex) {
throw new JmsTransportException("Could not set property", ex);
}
}
protected OutputStream getRequestOutputStream() throws IOException {
return new BytesMessageOutputStream(requestMessage);
}
protected void onSendAfterWrite(WebServiceMessage message) throws IOException {
MessageProducer messageProducer = null;
try {
messageProducer = session.createProducer(requestDestination);
messageProducer.setDeliveryMode(uri.getDeliveryMode());
messageProducer.setTimeToLive(uri.getTimeToLive());
messageProducer.setPriority(uri.getPriority());
if (uri.hasReplyTo()) {
responseDestination =
destinationResolver.resolveDestinationName(session, uri.getReplyTo(), uri.isPubSubDomain());
}
else {
responseDestination = session.createTemporaryQueue();
}
requestMessage.setJMSReplyTo(responseDestination);
connection.start();
messageProducer.send(requestMessage);
}
catch (JMSException ex) {
throw new JmsTransportException(ex);
}
finally {
JmsUtils.closeMessageProducer(messageProducer);
}
}
/*
* Receiving
*/
protected void onReceiveBeforeRead() throws IOException {
MessageConsumer messageConsumer = null;
try {
messageConsumer = session.createConsumer(responseDestination);
responseMessage = (BytesMessage) (receiveTimeout >= 0 ? messageConsumer.receive(receiveTimeout) :
messageConsumer.receive());
}
catch (JMSException ex) {
throw new JmsTransportException(ex);
}
finally {
JmsUtils.closeMessageConsumer(messageConsumer);
if (responseDestination instanceof TemporaryQueue) {
try {
((TemporaryQueue) responseDestination).delete();
}
catch (JMSException e) {
// ignore
}
}
}
}
protected boolean hasResponse() throws IOException {
return responseMessage != null;
}
protected Iterator getResponseHeaderNames() throws IOException {
try {
List headerNames = new ArrayList();
Enumeration propertyNames = responseMessage.getPropertyNames();
while (propertyNames.hasMoreElements()) {
String propertyName = (String) propertyNames.nextElement();
headerNames.add(JmsTransportUtils.jmsPropertyToHeader(propertyName));
}
return headerNames.iterator();
}
catch (JMSException ex) {
throw new JmsTransportException("Could not get property names", ex);
}
}
protected Iterator getResponseHeaders(String name) throws IOException {
try {
String propertyName = JmsTransportUtils.headerToJmsProperty(name);
String value = responseMessage.getStringProperty(propertyName);
if (value != null) {
return Collections.singletonList(value).iterator();
}
else {
return Collections.EMPTY_LIST.iterator();
}
}
catch (JMSException ex) {
throw new JmsTransportException("Could not get property value", ex);
}
}
protected InputStream getResponseInputStream() throws IOException {
return new BytesMessageInputStream(responseMessage);
}
public void close() throws IOException {
JmsUtils.closeSession(session);
ConnectionFactoryUtils.releaseConnection(connection, connectionFactory, true);
}
/*
* Faults
*/
public boolean hasFault() throws IOException {
if (responseMessage != null) {
try {
return responseMessage.getBooleanProperty(JmsTransportConstants.PROPERTY_IS_FAULT);
}
catch (JMSException ex) {
throw new JmsTransportException(ex);
}
}
else {
return false;
}
}
public void setFault(boolean fault) throws IOException {
try {
requestMessage.setBooleanProperty(JmsTransportConstants.PROPERTY_IS_FAULT, fault);
}
catch (JMSException ex) {
throw new JmsTransportException(ex);
}
}
}

View File

@@ -0,0 +1,68 @@
/*
* 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.jms;
import org.springframework.ws.transport.TransportConstants;
/**
* Declares JMS-specific transport constants.
*
* @author Arjen Poutsma
* @since 1.1.0
*/
public interface JmsTransportConstants extends TransportConstants {
String URI_SCHEME = "jms";
String PARAM_DELIVERY_MODE = "deliveryMode";
String PARAM_CONNECTION_FACTORY_NAME = "connectionFactoryName";
String PARAM_INITIAL_CONTEXT_FACTORY = "initialContextFactory";
String PARAM_JNDI_URL = "jndiURL";
String PARAM_TIME_TO_LIVE = "timeToLive";
String PARAM_PRIORITY = "priority";
String PARAM_DESTINATION_TYPE = "destinationType";
String PARAM_REPLY_TO_NAME = "replyToName";
String DESTINATION_TYPE_QUEUE = "queue";
String DESTINATION_TYPE_TOPIC = "topic";
String PROPERTY_PREFIX = "SOAPJMS_";
String PROPERTY_IS_FAULT = PROPERTY_PREFIX + "isFault";
String PROPERTY_SOAP_ACTION = PROPERTY_PREFIX + "soapAction";
String PROPERTY_CONTENT_LENGTH = PROPERTY_PREFIX + "contentLength";
String PROPERTY_CONTENT_TYPE = PROPERTY_PREFIX + "contentType";
String PROPERTY_BINDING_VERSION = PROPERTY_PREFIX + "bindingVersion";
String PROPERTY_TARGET_SERVICE = PROPERTY_PREFIX + "targetService";
String PROPERTY_REQUEST_IRI = PROPERTY_PREFIX + "requestIRI";
String PROPERTY_SOAP_MEP = PROPERTY_PREFIX + "soapMEP";
}

View File

@@ -0,0 +1,47 @@
/*
* 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.jms;
import javax.jms.JMSException;
import org.springframework.ws.transport.TransportException;
/**
* Exception that is thrown when an error occurs in the JMS transport.
*
* @author Arjen Poutsma
* @since 1.1.0
*/
public class JmsTransportException extends TransportException {
private final JMSException jmsException;
public JmsTransportException(String msg, JMSException ex) {
super(msg + ": " + ex.getMessage());
jmsException = ex;
}
public JmsTransportException(JMSException ex) {
super(ex.getMessage());
jmsException = ex;
}
public JMSException getJmsException() {
return jmsException;
}
}

View File

@@ -0,0 +1,134 @@
/*
* 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.jms;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.Message;
import javax.jms.Queue;
import javax.jms.Topic;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.ws.transport.support.ParameterizedUri;
/**
* @author Arjen Poutsma
* @see <a href="http://mail-archives.apache.org/mod_mbox/ws-axis-dev/200701.mbox/raw/%3C80A43FC052CE3949A327527DCD5D6B27020FB65C@MAIL01.bedford.progress.com%3E/2">RI
* Scheme for Java Message Service 1.0 RC1</a>
*/
public class JmsUri extends ParameterizedUri implements JmsTransportConstants {
public JmsUri(String uri) {
super(uri);
validateParameters();
}
private void validateParameters() {
validateIntegerParameter(PARAM_DELIVERY_MODE);
validateIntegerParameter(PARAM_PRIORITY);
validateIntegerParameter(PARAM_TIME_TO_LIVE);
String destinationType = getDestinationType();
if (StringUtils.hasLength(destinationType)) {
Assert.isTrue(
DESTINATION_TYPE_QUEUE.equals(destinationType) || DESTINATION_TYPE_TOPIC.equals(destinationType),
"Invalid " + PARAM_DESTINATION_TYPE + ": [" + destinationType + "]. Expected '" +
DESTINATION_TYPE_QUEUE + "' or '" + DESTINATION_TYPE_TOPIC + "'");
}
}
private void validateIntegerParameter(String paramName) {
String paramValue = getParameter(paramName);
if (StringUtils.hasLength(paramValue)) {
try {
Integer.parseInt(paramValue);
}
catch (NumberFormatException ex) {
throw new IllegalArgumentException("Invalid " + paramName + ": [" + paramValue + "]. Not an integer.");
}
}
}
/**
* Returns whether the request message is persistent or not.
*
* @see DeliveryMode#NON_PERSISTENT
* @see DeliveryMode#PERSISTENT
*/
public int getDeliveryMode() {
return getIntegerParameter(PARAM_DELIVERY_MODE, Message.DEFAULT_DELIVERY_MODE);
}
public String getDestination() {
return super.getDestination();
}
/**
* Specifies whether the destination is a {@link Queue} or a {@link Topic}, with the value "<code>queue</code>" or
* "<code>topic</code>", respectively.
*/
public String getDestinationType() {
return getParameter(PARAM_DESTINATION_TYPE);
}
/**
* Returns the JMS priority associated with the request message.
*
* @see Message#setJMSPriority(int)
*/
public int getPriority() {
return getIntegerParameter(PARAM_PRIORITY, Message.DEFAULT_PRIORITY);
}
/**
* Returns the lifetime, in milliseconds, of the request message.
*/
public long getTimeToLive() {
String paramValue = getParameter(PARAM_TIME_TO_LIVE);
return paramValue != null ? Long.parseLong(paramValue) : Message.DEFAULT_TIME_TO_LIVE;
}
private int getIntegerParameter(String paramName, int defaultValue) {
String paramValue = getParameter(paramName);
return paramValue != null ? Integer.parseInt(paramValue) : defaultValue;
}
/**
* Indicates whether this URI has a reply-to name.
*/
public boolean hasReplyTo() {
return StringUtils.hasLength(getReplyTo());
}
/**
* Returns the reply-to name.
*
* @see Message#setJMSReplyTo(Destination)
*/
public String getReplyTo() {
return getParameter(PARAM_REPLY_TO_NAME);
}
/**
* Return whether the Publish/Subscribe domain ({@link javax.jms.Topic Topics}) is used. Otherwise, the
* Point-to-Point domain ({@link javax.jms.Queue Queues}) is used.
*/
public boolean isPubSubDomain() {
return DESTINATION_TYPE_TOPIC.equals(getDestinationType());
}
}

View File

@@ -0,0 +1,157 @@
/*
* 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.jms;
import javax.ejb.EJBException;
import javax.ejb.MessageDrivenBean;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.naming.NamingException;
import org.springframework.ejb.support.AbstractJmsMessageDrivenBean;
import org.springframework.jms.connection.ConnectionFactoryUtils;
import org.springframework.jms.support.JmsUtils;
import org.springframework.jndi.JndiLookupFailureException;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.transport.WebServiceMessageReceiver;
/**
* EJB {@link MessageDrivenBean} that can be used to handleMessage incoming JMS messages.
* <p/>
* This class needs a JMS {@link ConnectionFactory}, and a {@link WebServiceMessageFactory} and {@link
* WebServiceMessageReceiver} to operate. By default, these are obtained by doing a bean lookup on the bean factory
* provided by {@link #getBeanFactory()} the super class.
*
* @author Arjen Poutsma
* @see #createConnectionFactory()
* @see #createMessageFactory()
* @see #createMessageReceiver()
*/
public class WebServiceMessageDrivenBean extends AbstractJmsMessageDrivenBean {
/** Well-known name for the {@link ConnectionFactory} object in the bean factory for this bean. */
public static final String CONNECTION_FACTORY_BEAN_NAME = "connectionFactory";
/** Well-known name for the {@link WebServiceMessageFactory} bean in the bean factory for this bean. */
public static final String MESSAGE_FACTORY_BEAN_NAME = "messageFactory";
/** Well-known name for the {@link WebServiceMessageReceiver} object in the bean factory for this bean. */
public static final String MESSAGE_RECEIVER_BEAN_NAME = "messageReceiver";
private JmsMessageReceiver delegate;
private ConnectionFactory connectionFactory;
/** Delegates to {@link JmsMessageReceiver#handleMessage(Message,Session)}. */
public void onMessage(Message message) {
Connection connection = null;
Session session = null;
try {
connection = createConnection(connectionFactory);
session = createSession(connection);
delegate.handleMessage(message, session);
}
catch (JmsTransportException ex) {
throw JmsUtils.convertJmsAccessException(ex.getJmsException());
}
catch (JMSException ex) {
throw JmsUtils.convertJmsAccessException(ex);
}
catch (Exception ex) {
throw new EJBException(ex);
}
finally {
JmsUtils.closeSession(session);
ConnectionFactoryUtils.releaseConnection(connection, connectionFactory, true);
}
}
/**
* Creates a new {@link Connection}, {@link WebServiceMessageFactory}, and {@link WebServiceMessageReceiver}.
*
* @see #createConnectionFactory()
* @see #createMessageFactory()
* @see #createMessageReceiver()
*/
protected void onEjbCreate() {
try {
connectionFactory = createConnectionFactory();
delegate = new JmsMessageReceiver();
delegate.setMessageFactory(createMessageFactory());
delegate.setMessageReceiver(createMessageReceiver());
}
catch (NamingException ex) {
throw new JndiLookupFailureException("Could not create connection", ex);
}
catch (JMSException ex) {
throw JmsUtils.convertJmsAccessException(ex);
}
catch (Exception ex) {
throw new EJBException(ex);
}
}
/** Creates a connection factory. Default implemantion does a bean lookup for {@link #CONNECTION_FACTORY_BEAN_NAME}. */
protected ConnectionFactory createConnectionFactory() throws Exception {
return (ConnectionFactory) getBeanFactory().getBean(CONNECTION_FACTORY_BEAN_NAME, ConnectionFactory.class);
}
/** Creates a message factory. Default implemantion does a bean lookup for {@link #MESSAGE_FACTORY_BEAN_NAME}. */
protected WebServiceMessageFactory createMessageFactory() {
return (WebServiceMessageFactory) getBeanFactory()
.getBean(MESSAGE_FACTORY_BEAN_NAME, WebServiceMessageFactory.class);
}
/** Creates a connection factory. Default implemantion does a bean lookup for {@link #MESSAGE_RECEIVER_BEAN_NAME}. */
protected WebServiceMessageReceiver createMessageReceiver() {
return (WebServiceMessageReceiver) getBeanFactory()
.getBean(MESSAGE_RECEIVER_BEAN_NAME, WebServiceMessageReceiver.class);
}
/**
* Create a JMS {@link Connection} using the given {@link ConnectionFactory}.
* <p/>
* This implementation uses JMS 1.1 API.
*
* @param connectionFactory the JMS ConnectionFactory to create a Connection with
* @return the new JMS Connection
* @throws JMSException if thrown by JMS API methods
* @see ConnectionFactory#createConnection()
*/
protected Connection createConnection(ConnectionFactory connectionFactory) throws JMSException {
return connectionFactory.createConnection();
}
/**
* Creates a JMS {@link Session}. Default implemantion creates a non-transactional, {@link Session#AUTO_ACKNOWLEDGE
* auto acknowledged} session.
* <p/>
* This implementation uses JMS 1.1 API.
*
* @param connection the JMS Connection to create a Session for
* @return the new JMS Session
* @throws JMSException if thrown by JMS API methods
* @see Connection#createSession(boolean,int)
*/
protected Session createSession(Connection connection) throws JMSException {
return connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2006 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.jms;
import javax.jms.BytesMessage;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import org.springframework.jms.listener.SessionAwareMessageListener;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.transport.WebServiceMessageReceiver;
/**
* Spring-2.0 {@link SessionAwareMessageListener} that can be used to handle incoming JMS messages.
* <p/>
* Requires a {@link WebServiceMessageFactory} which is used to convert the incoming JMS {@link BytesMessage} into a
* {@link WebServiceMessage}, and passes that to the {@link WebServiceMessageReceiver} {@link
* #setMessageReceiver(WebServiceMessageReceiver) registered}.
*
* @author Arjen Poutsma
* @see #setMessageFactory(org.springframework.ws.WebServiceMessageFactory)
* @see #setMessageReceiver(org.springframework.ws.transport.WebServiceMessageReceiver)
* @since 1.1.0
*/
public class WebServiceMessageListener extends JmsMessageReceiver implements SessionAwareMessageListener {
public void onMessage(Message message, Session session) throws JMSException {
try {
handleMessage(message, session);
}
catch (JmsTransportException ex) {
throw ex.getJmsException();
}
catch (Exception ex) {
JMSException jmsException = new JMSException(ex.getMessage());
jmsException.setLinkedException(ex);
throw jmsException;
}
}
}

View File

@@ -0,0 +1,5 @@
<html>
<body>
Package providing support for handling messages via JMS.
</body>
</html>

View File

@@ -0,0 +1,69 @@
/*
* 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.jms.support;
import org.springframework.ws.transport.jms.JmsTransportConstants;
/**
* Collection of utility methods to work with JMS transports. Includes methods to convert from transport header names to
* JMS Properties and vice-versa.
*
* @author Arjen Poutsma
* @since 1.1.0
*/
public class JmsTransportUtils {
private static final String[] CONVERSION_TABLE = new String[]{JmsTransportConstants.HEADER_CONTENT_TYPE,
JmsTransportConstants.PROPERTY_CONTENT_TYPE, JmsTransportConstants.HEADER_CONTENT_LENGTH,
JmsTransportConstants.PROPERTY_CONTENT_LENGTH, JmsTransportConstants.HEADER_SOAP_ACTION,
JmsTransportConstants.PROPERTY_SOAP_ACTION};
private JmsTransportUtils() {
}
/**
* Converts the given transport header to a JMS property name. Returns the given header name if no match is found.
*
* @param headerName the header name to transform
* @return the JMS property name
*/
public static String headerToJmsProperty(String headerName) {
for (int i = 0; i < CONVERSION_TABLE.length; i = i + 2) {
if (CONVERSION_TABLE[i].equals(headerName)) {
return CONVERSION_TABLE[i + 1];
}
}
return headerName;
}
/**
* Converts the given JMS property name to a transport header name. Returns the given property name if no match is
* found.
*
* @param propertyName the JMS property name to transform
* @return the transport header name
*/
public static String jmsPropertyToHeader(String propertyName) {
for (int i = 1; i < CONVERSION_TABLE.length; i = i + 2) {
if (CONVERSION_TABLE[i].equals(propertyName)) {
return CONVERSION_TABLE[i - 1];
}
}
return propertyName;
}
}

View File

@@ -0,0 +1,5 @@
<html>
<body>
Classes supporting the org.springframework.ws.transport.jms package.
</body>
</html>

View File

@@ -0,0 +1,84 @@
/*
* 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 java.util.Map;
import java.util.StringTokenizer;
import org.springframework.core.CollectionFactory;
import org.springframework.util.Assert;
/** @author Arjen Poutsma */
public class ParameterizedUri {
private final String uri;
private final String scheme;
// keys are string parameter names; values are string parameter values
private final Map parameters = CollectionFactory.createLinkedCaseInsensitiveMapIfPossible(5);
private final String destination;
public ParameterizedUri(String uri) {
Assert.hasLength(uri, "'uri' must not be empty");
this.uri = uri;
int scIdx = uri.indexOf(':');
Assert.isTrue(scIdx != -1, uri + " does contain scheme");
scheme = uri.substring(0, scIdx);
Assert.isTrue(uri.length() > scheme.length(), uri + " does not have a destination");
int paramStart = uri.indexOf('?');
if (paramStart == -1) {
destination = uri.substring(scIdx + 1);
}
else {
destination = uri.substring(scIdx + 1, paramStart);
parseParameters(uri.substring(paramStart + 1));
}
}
private void parseParameters(String parametersString) {
StringTokenizer params = new StringTokenizer(parametersString, "&");
while (params.hasMoreTokens()) {
String param = params.nextToken();
int paramSep = param.indexOf('=');
if (paramSep == -1) {
throw new IllegalArgumentException(param + " is not a valid parameter: it has no '='");
}
String paramName = param.substring(0, paramSep);
String paramValue = param.substring(paramSep + 1);
parameters.put(paramName, paramValue);
}
}
/** Returns the destination of the uri. */
protected String getDestination() {
return destination;
}
public String toString() {
return uri;
}
protected String getParameter(String paramName) {
return (String) parameters.get(paramName);
}
protected boolean hasParameter(String paramName) {
return parameters.containsKey(paramName);
}
}

View File

@@ -0,0 +1,59 @@
/*
* 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.InitializingBean;
import org.springframework.util.Assert;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.WebServiceMessageReceiver;
/**
* Base class for server-side transport objects which have a predefined {@link WebServiceMessageReceiver}.
*
* @author Arjen Poutsma
* @see #handleConnection(WebServiceConnection)
* @since 1.1.0
*/
public abstract class SimpleWebServiceMessageReceiverObjectSupport extends WebServiceMessageReceiverObjectSupport
implements InitializingBean {
private WebServiceMessageReceiver messageReceiver;
/**
* Returns the <code>WebServiceMessageReceiver</code> used by this listener.
*/
public WebServiceMessageReceiver getMessageReceiver() {
return messageReceiver;
}
/**
* Sets the <code>WebServiceMessageReceiver</code> used by this listener.
*/
public void setMessageReceiver(WebServiceMessageReceiver messageReceiver) {
this.messageReceiver = messageReceiver;
}
public void afterPropertiesSet() throws Exception {
super.afterPropertiesSet();
Assert.notNull(getMessageReceiver(), "messageReceiver must not be null");
}
protected final void handleConnection(WebServiceConnection connection) throws Exception {
handleConnection(connection, getMessageReceiver());
}
}

View File

@@ -0,0 +1,34 @@
/*
* 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 javax.xml.transform.Transformer;
import org.springframework.ws.context.MessageContext;
import org.springframework.xml.transform.TransformerObjectSupport;
import org.springframework.util.Assert;
public class SimpleTestingMessageReceiver extends TransformerObjectSupport implements WebServiceMessageReceiver {
public void receive(MessageContext messageContext) throws Exception {
Assert.notNull(messageContext, "MessageContext is null");
logger.info("Received message");
Transformer transformer = createTransformer();
transformer.transform(messageContext.getRequest().getPayloadSource(),
messageContext.getResponse().getPayloadResult());
}
}

View File

@@ -0,0 +1,130 @@
/*
* 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.jms;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.jms.BytesMessage;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPConstants;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.saaj.SaajSoapMessage;
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
import org.springframework.ws.transport.WebServiceConnection;
public class JmsMessageSenderIntegrationTest extends AbstractDependencyInjectionSpringContextTests {
private JmsMessageSender messageSender;
private JmsTemplate jmsTemplate;
private MessageFactory messageFactory;
private static final String REQUEST_QUEUE_URI = "jms:RequestQueue";
private static final String SOAP_ACTION = "\"http://springframework.org/DoIt\"";
protected void onSetUp() throws Exception {
messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
}
protected String[] getConfigLocations() {
return new String[]{"classpath:org/springframework/ws/transport/jms/jms-sender-applicationContext.xml"};
}
public void setJmsTemplate(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
public void setMessageSender(JmsMessageSender messageSender) {
this.messageSender = messageSender;
}
public void testSendAndReceiveQueue() throws Exception {
WebServiceConnection connection = null;
try {
connection = messageSender.createConnection(REQUEST_QUEUE_URI);
SoapMessage soapRequest = new SaajSoapMessage(messageFactory.createMessage());
soapRequest.setSoapAction(SOAP_ACTION);
connection.send(soapRequest);
BytesMessage request = (BytesMessage) jmsTemplate.receive();
validateMessage(request);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
messageFactory.createMessage().writeTo(bos);
final byte[] buf = bos.toByteArray();
jmsTemplate.send(request.getJMSReplyTo(), new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
BytesMessage response = session.createBytesMessage();
response.setStringProperty(JmsTransportConstants.PROPERTY_BINDING_VERSION, "1.0");
response.setIntProperty(JmsTransportConstants.PROPERTY_CONTENT_LENGTH, buf.length);
response.setStringProperty(JmsTransportConstants.PROPERTY_CONTENT_TYPE, "text/xml");
response.setBooleanProperty(JmsTransportConstants.PROPERTY_IS_FAULT, false);
response.setStringProperty(JmsTransportConstants.PROPERTY_REQUEST_IRI, REQUEST_QUEUE_URI);
response.setStringProperty(JmsTransportConstants.PROPERTY_SOAP_ACTION, SOAP_ACTION);
response.writeBytes(buf);
return response;
}
});
SoapMessage response = (SoapMessage) connection.receive(new SaajSoapMessageFactory(messageFactory));
assertNotNull("No response received", response);
assertEquals("Invalid SOAPAction", SOAP_ACTION, response.getSoapAction());
assertFalse("Message is fault", response.hasFault());
}
finally {
if (connection != null) {
connection.close();
}
}
}
private void validateMessage(BytesMessage message) throws JMSException, IOException {
assertEquals("Invalid SOAPAction", SOAP_ACTION,
message.getStringProperty(JmsTransportConstants.PROPERTY_SOAP_ACTION));
assertEquals("Invalid binding version", "1.0",
message.getStringProperty(JmsTransportConstants.PROPERTY_BINDING_VERSION));
assertEquals("Invalid service IRI", REQUEST_QUEUE_URI,
message.getStringProperty(JmsTransportConstants.PROPERTY_REQUEST_IRI));
assertFalse("Message is Fault", message.getBooleanProperty(JmsTransportConstants.PROPERTY_IS_FAULT));
assertTrue("Invalid Content Type",
message.getStringProperty(JmsTransportConstants.PROPERTY_CONTENT_TYPE).indexOf("text/xml") != -1);
assertTrue("No Content Length", message.getIntProperty(JmsTransportConstants.PROPERTY_CONTENT_LENGTH) > 0);
assertTrue("Message has no contents", getMessageContents(message).length() > 0);
}
private String getMessageContents(BytesMessage message) throws JMSException, IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = message.readBytes(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
out.flush();
return out.toString("UTF-8");
}
}

View File

@@ -0,0 +1,76 @@
/*
* 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.jms;
import junit.framework.TestCase;
public class JmsUriTest extends TestCase {
public void testJmsUri() {
JmsUri uri = new JmsUri("jms:news?connectionFactoryName=SOAPJMSFactory&" + "deliveryMode=2&" +
"destinationType=topic&" + "initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory&" +
"jndiURL=theJndiURL&" + "priority=8&" + "timeToLive=10&" + "replyToName=interested&" +
"userprop=mystuff");
assertEquals("Invalid delivery mode", 2, uri.getDeliveryMode());
assertEquals("Invalid destination", "news", uri.getDestination());
assertEquals("Invalid destination type", "topic", uri.getDestinationType());
assertTrue("Invalid pub sub domain", uri.isPubSubDomain());
assertEquals("Invalid prority", 8, uri.getPriority());
assertEquals("Invalid time to live", 10, uri.getTimeToLive());
assertEquals("Invalid reply to name", "interested", uri.getReplyTo());
}
public void testGetDestinationNoParams() {
JmsUri uri = new JmsUri("jms:news");
assertEquals("Invalid destination", "news", uri.getDestination());
}
public void testInvalidDeliveryMode() {
testIllegalArgument("jms:news?deliveryMode=abc");
}
public void testInvalidPriority() {
testIllegalArgument("jms:news?priority=abc");
}
public void testInvalidTimeToLive() {
testIllegalArgument("jms:news?timeToLive=abc");
}
public void testInvalidDestinationType() {
testIllegalArgument("jms:news?destinationType=abc");
}
public void testEmpty() {
testIllegalArgument("");
}
public void testIllegalParam() {
testIllegalArgument("jms:news?bla");
}
private void testIllegalArgument(String uri) {
try {
new JmsUri(uri);
fail("Expected IllegalArgumentException for uri [" + uri + "]");
}
catch (IllegalArgumentException ex) {
//expected
}
}
}

View File

@@ -0,0 +1,116 @@
/*
*/
/*
* Copyright 2006 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.jms;
import javax.jms.BytesMessage;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.StreamMessage;
import junit.framework.TestCase;
import org.codehaus.activemq.message.ActiveMQBytesMessage;
import org.codehaus.activemq.message.ActiveMQTopic;
import org.easymock.MockControl;
import org.springframework.ws.MockWebServiceMessageFactory;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.server.endpoint.MessageEndpoint;
public class MessageEndpointMessageListenerTest extends TestCase {
private static final String REQUEST = " <SOAP-ENV:Envelope\n" +
" 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=\"Some-URI\">\n" + " <symbol>DIS</symbol>\n" +
" </m:GetLastTradePrice>\n" + " </SOAP-ENV:Body>\n" + "</SOAP-ENV:Envelope>";
private WebServiceMessageListener messageListener;
private BytesMessage request;
private MockControl sessionControl;
private Session sessionMock;
protected void setUp() throws Exception {
messageListener = new WebServiceMessageListener();
request = new ActiveMQBytesMessage();
request.writeBytes(REQUEST.getBytes("UTF-8"));
messageListener.setMessageFactory(new MockWebServiceMessageFactory());
sessionControl = MockControl.createControl(Session.class);
sessionMock = (Session) sessionControl.getMock();
}
public void testOnMessageInvalidMessage() throws Exception {
MockControl mockControl = MockControl.createControl(StreamMessage.class);
StreamMessage message = (StreamMessage) mockControl.getMock();
try {
messageListener.onMessage(message, sessionMock);
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException ex) {
// expected
}
}
public void testOnMessageNoResponse() throws Exception {
MessageEndpoint endpoint = new MessageEndpoint() {
public void invoke(MessageContext messageContext) throws Exception {
}
};
messageListener.setMessageReceiver(endpoint);
request.reset();
messageListener.onMessage(request, sessionMock);
}
public void testOnMessageResponse() throws Exception {
MockControl producerControl = MockControl.createControl(MessageProducer.class);
MessageProducer producerMock = (MessageProducer) producerControl.getMock();
BytesMessage response = new ActiveMQBytesMessage();
String correlationId = "correlationId";
Destination replyTo = new ActiveMQTopic();
request.setJMSCorrelationID(correlationId);
request.setJMSReplyTo(replyTo);
request.reset();
sessionControl.expectAndReturn(sessionMock.createBytesMessage(), response);
sessionControl.expectAndReturn(sessionMock.createProducer(replyTo), producerMock);
producerMock.marshalSendAndReceive(response);
sessionControl.replay();
producerControl.replay();
MessageEndpoint endpoint = new MessageEndpoint() {
public void invoke(MessageContext messageContext) throws Exception {
messageContext.getResponse();
}
};
messageListener.setMessageReceiver(endpoint);
messageListener.onMessage(request, sessionMock);
sessionControl.verify();
producerControl.verify();
assertEquals("Invalid correlationId", correlationId, response.getJMSCorrelationID());
}
}*/

View File

@@ -0,0 +1,95 @@
/*
* 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.jms;
import javax.jms.BytesMessage;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.Topic;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
public class WebServiceMessageListenerIntegrationTest extends AbstractDependencyInjectionSpringContextTests {
private static final String CONTENT =
"<SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>" + "<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></SOAP-ENV:Envelope>";
private JmsTemplate jmsTemplate;
private Queue responseQueue;
private Queue requestQueue;
private Topic requestTopic;
public WebServiceMessageListenerIntegrationTest() {
setAutowireMode(AUTOWIRE_BY_NAME);
}
public void setJmsTemplate(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
public void setRequestQueue(Queue requestQueue) {
this.requestQueue = requestQueue;
}
public void setRequestTopic(Topic requestTopic) {
this.requestTopic = requestTopic;
}
public void setResponseQueue(Queue responseQueue) {
this.responseQueue = responseQueue;
}
protected String[] getConfigLocations() {
return new String[]{"classpath:org/springframework/ws/transport/jms/jms-receiver-applicationContext.xml"};
}
public void testReceiveQueue() throws Exception {
final byte[] b = CONTENT.getBytes("UTF-8");
jmsTemplate.send(requestQueue, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
BytesMessage request = session.createBytesMessage();
request.setJMSReplyTo(responseQueue);
request.writeBytes(b);
return request;
}
});
BytesMessage response = (BytesMessage) jmsTemplate.receive(responseQueue);
assertNotNull("No response received", response);
}
public void testReceiveTopic() throws Exception {
final byte[] b = CONTENT.getBytes("UTF-8");
jmsTemplate.send(requestTopic, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
BytesMessage request = session.createBytesMessage();
request.writeBytes(b);
return request;
}
});
Thread.sleep(100);
}
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.transport.jms.support;
import junit.framework.TestCase;
import org.springframework.ws.transport.jms.support.JmsTransportUtils;
public class JmsTransportUtilsTest extends TestCase {
public void testHeaderToJmsProperty() throws Exception {
String result = JmsTransportUtils.headerToJmsProperty("SOAPAction");
assertEquals("Invalid result", "SOAPJMS_soapAction", result);
}
}

View File

@@ -0,0 +1,7 @@
log4j.rootCategory=WARN, stdout
log4j.logger.org.springframework.ws=DEBUG
log4j.logger.org.springframework.jms=DEBUG
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n

View File

@@ -0,0 +1,47 @@
<?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="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://localhost?broker.persistent=false"/>
</bean>
<bean id="requestQueue" class="org.apache.activemq.command.ActiveMQQueue">
<property name="physicalName" value="RequestQueue"/>
</bean>
<bean id="requestTopic" class="org.apache.activemq.command.ActiveMQTopic">
<property name="physicalName" value="RequestTopic"/>
</bean>
<bean id="responseQueue" class="org.apache.activemq.command.ActiveMQQueue">
<property name="physicalName" value="ResponseQueue"/>
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory"/>
</bean>
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="requestQueue"/>
<property name="messageListener" ref="messageListener"/>
</bean>
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="requestTopic"/>
<property name="messageListener" ref="messageListener"/>
</bean>
<bean id="messageListener" class="org.springframework.ws.transport.jms.WebServiceMessageListener">
<property name="messageFactory">
<bean class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
</property>
<property name="messageReceiver" ref="messageReceiver"/>
</bean>
<bean id="messageReceiver" class="org.springframework.ws.transport.SimpleTestingMessageReceiver"/>
</beans>

View File

@@ -0,0 +1,23 @@
<?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="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://localhost?broker.persistent=false"/>
</bean>
<bean id="requestQueue" class="org.apache.activemq.command.ActiveMQQueue">
<property name="physicalName" value="RequestQueue"/>
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="defaultDestination" ref="requestQueue"/>
</bean>
<bean id="messageSender" class="org.springframework.ws.transport.jms.JmsMessageSender">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="receiveTimeout" value="10"/>
</bean>
</beans>