diff --git a/sandbox/src/main/java/org/springframework/ws/transport/jms/BytesMessageInputStream.java b/sandbox/src/main/java/org/springframework/ws/transport/jms/BytesMessageInputStream.java new file mode 100644 index 00000000..8e267bc6 --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/transport/jms/BytesMessageInputStream.java @@ -0,0 +1,72 @@ +/* + * 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 javax.jms.BytesMessage}. + * + * @author Arjen Poutsma + */ +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); + } + } +} diff --git a/sandbox/src/main/java/org/springframework/ws/transport/jms/BytesMessageOutputStream.java b/sandbox/src/main/java/org/springframework/ws/transport/jms/BytesMessageOutputStream.java new file mode 100644 index 00000000..25d09f7d --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/transport/jms/BytesMessageOutputStream.java @@ -0,0 +1,63 @@ +/* + * 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 javax.jms.BytesMessage}. + * + * @author Arjen Poutsma + */ +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); + } + } +} diff --git a/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsMessageSender.java b/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsMessageSender.java new file mode 100644 index 00000000..7cb8f8e1 --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsMessageSender.java @@ -0,0 +1,135 @@ +/* + * 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.JMSException; +import javax.jms.Queue; +import javax.jms.QueueConnection; +import javax.jms.QueueConnectionFactory; +import javax.jms.QueueSession; +import javax.jms.Session; + +import org.springframework.jms.support.destination.DestinationResolver; +import org.springframework.jms.support.destination.DynamicDestinationResolver; +import org.springframework.util.Assert; +import org.springframework.ws.transport.WebServiceConnection; +import org.springframework.ws.transport.WebServiceMessageSender; + +/** @author Arjen Poutsma */ +public class JmsMessageSender implements WebServiceMessageSender { + + /** Default timeout for receive operations. */ + public static final long DEFAULT_RECEIVE_TIMEOUT = 0; + + private QueueConnectionFactory connectionFactory; + + private Object queue; + + private DestinationResolver destinationResolver = new DynamicDestinationResolver(); + + private long receiveTimeout = DEFAULT_RECEIVE_TIMEOUT; + + /** Set the QueueConnectionFactory to use for obtaining JMS QueueConnections. */ + public void setConnectionFactory(QueueConnectionFactory connectionFactory) { + this.connectionFactory = connectionFactory; + } + + /** Set the target Queue to send invoker requests to. */ + public void setQueue(Queue queue) { + this.queue = queue; + } + + /** Set the name of target queue to send invoker requests to. */ + public void setQueueName(String queueName) { + queue = queueName; + } + + /** Set the timeout to use for receive calls. The default is 0, which means no timeout. */ + public void setReceiveTimeout(long receiveTimeout) { + this.receiveTimeout = receiveTimeout; + } + + /** + * Set the DestinationResolver that is to be used to resolve Queue references for this accessor.

The default + * resolver is a DynamicDestinationResolver. Specify a JndiDestinationResolver for resolving destination names as + * JNDI locations. + * + * @param destinationResolver the DestinationResolver that is to be used + * @see org.springframework.jms.support.destination.DynamicDestinationResolver + * @see org.springframework.jms.support.destination.JndiDestinationResolver + */ + public void setDestinationResolver(DestinationResolver destinationResolver) { + Assert.notNull(destinationResolver, "DestinationResolver must not be null"); + this.destinationResolver = destinationResolver; + } + + public void afterPropertiesSet() { + if (connectionFactory == null) { + throw new IllegalArgumentException("connectionFactory is required"); + } + if (queue == null) { + throw new IllegalArgumentException("'queue' or 'queueName' is required"); + } + } + + /** + * Resolve this accessor's target queue. + * + * @param session the current JMS Session + * @return the resolved target Queue + * @throws JMSException if resolution failed + */ + protected Queue resolveQueue(Session session) throws JMSException { + if (queue instanceof Queue) { + return (Queue) queue; + } + else if (queue instanceof String) { + return resolveQueueName(session, (String) queue); + } + else { + throw new javax.jms.IllegalStateException( + "Queue object [" + queue + "] is neither a [javax.jms.Queue] nor a queue name String"); + } + } + + /** + * Resolve the given queue name into a JMS {@link javax.jms.Queue}, via this accessor's {@link + * DestinationResolver}. + * + * @param session the current JMS Session + * @param queueName the name of the queue + * @return the located Queue + * @throws JMSException if resolution failed + * @see #setDestinationResolver + */ + protected Queue resolveQueueName(Session session, String queueName) throws JMSException { + return (Queue) destinationResolver.resolveDestinationName(session, queueName, false); + } + + public WebServiceConnection createConnection() throws IOException { + try { + QueueConnection con = connectionFactory.createQueueConnection(); + QueueSession session = con.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); + Queue queueToUse = resolveQueue(session); + return new JmsSendingWebServiceConnection(con, session, queueToUse, receiveTimeout); + } + catch (JMSException ex) { + throw new JmsTransportException(ex); + } + } +} diff --git a/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsReceivingWebServiceConnection.java b/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsReceivingWebServiceConnection.java new file mode 100644 index 00000000..20ee524a --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsReceivingWebServiceConnection.java @@ -0,0 +1,135 @@ +/* + * 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.Collections; +import java.util.Iterator; +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.util.StringUtils; +import org.springframework.ws.transport.AbstractReceivingWebServiceConnection; +import org.springframework.ws.transport.support.EnumerationIterator; + +/** @author Arjen Poutsma */ +public class JmsReceivingWebServiceConnection extends AbstractReceivingWebServiceConnection { + + private final BytesMessage requestMessage; + + private final Session session; + + private BytesMessage responseMessage; + + public JmsReceivingWebServiceConnection(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; + } + + public void close() throws IOException { + try { + session.close(); + } + catch (JMSException ex) { + throw new JmsTransportException("Could not close session", ex); + } + } + + protected void sendResponse() throws IOException { + if (responseMessage != null) { + MessageProducer producer = null; + try { + if (requestMessage.getJMSReplyTo() != null) { + producer = session.createProducer(requestMessage.getJMSReplyTo()); + producer.send(responseMessage); + } + else { + logger.warn("Incoming message has no ReplyTo set, not sending response"); + } + } + catch (JMSException ex) { + throw new JmsTransportException("Could not send response", ex); + } + finally { + if (producer != null) { + JmsUtils.closeMessageProducer(producer); + } + } + } + } + + private void createResponseMessage() throws IOException { + if (responseMessage == null) { + try { + responseMessage = session.createBytesMessage(); + String correlationID = requestMessage.getJMSCorrelationID(); + if (StringUtils.hasLength(correlationID)) { + responseMessage.setJMSCorrelationID(correlationID); + } + } + catch (JMSException ex) { + throw new JmsTransportException("Could not create response message", ex); + } + } + } + + protected void addResponseHeader(String name, String value) throws IOException { + try { + createResponseMessage(); + responseMessage.setStringProperty(name, value); + } + catch (JMSException ex) { + throw new JmsTransportException("Could not set property", ex); + } + } + + protected OutputStream getResponseOutputStream() throws IOException { + createResponseMessage(); + return new BytesMessageOutputStream(responseMessage); + } + + protected Iterator getRequestHeaderNames() throws IOException { + try { + return new EnumerationIterator(requestMessage.getPropertyNames()); + } + 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); + } +} diff --git a/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsSendingWebServiceConnection.java b/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsSendingWebServiceConnection.java new file mode 100644 index 00000000..f90eb4ab --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsSendingWebServiceConnection.java @@ -0,0 +1,179 @@ +/* + * 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.Collections; +import java.util.Iterator; +import javax.jms.BytesMessage; +import javax.jms.JMSException; +import javax.jms.Queue; +import javax.jms.QueueConnection; +import javax.jms.QueueReceiver; +import javax.jms.QueueSender; +import javax.jms.QueueSession; +import javax.jms.TemporaryQueue; + +import org.springframework.util.Assert; +import org.springframework.ws.transport.AbstractSendingWebServiceConnection; +import org.springframework.ws.transport.support.EnumerationIterator; + +/** @author Arjen Poutsma */ +public class JmsSendingWebServiceConnection extends AbstractSendingWebServiceConnection { + + private final BytesMessage requestMessage; + + private BytesMessage responseMessage; + + private final QueueSession session; + + private TemporaryQueue responseQueue = null; + + private QueueConnection connection; + + private long receiveTimeout; + + private Queue queue; + + public JmsSendingWebServiceConnection(QueueConnection connection, + QueueSession session, + Queue queue, + long receiveTimeout) throws JMSException { + Assert.notNull(connection, "connection must not be null"); + Assert.notNull(session, "session must not be null"); + Assert.notNull(queue, "queue must not be null"); + this.connection = connection; + this.session = session; + this.queue = queue; + this.receiveTimeout = receiveTimeout; + requestMessage = session.createBytesMessage(); + } + + public void close() throws IOException { + try { + session.close(); + } + catch (JMSException ex) { + throw new JmsTransportException("Could not close session", ex); + } + try { + connection.close(); + } + catch (JMSException ex) { + throw new JmsTransportException("Could not close connection", ex); + } + } + + protected void addRequestHeader(String name, String value) throws IOException { + try { + requestMessage.setStringProperty(name, value); + } + catch (JMSException ex) { + throw new JmsTransportException("Could not set property", ex); + } + } + + protected OutputStream getRequestOutputStream() throws IOException { + return new BytesMessageOutputStream(requestMessage); + } + + protected void sendRequest() throws IOException { + QueueSender sender = null; + try { + sender = session.createSender(queue); + responseQueue = session.createTemporaryQueue(); + requestMessage.setJMSReplyTo(responseQueue); + connection.start(); + sender.send(requestMessage); + } + catch (JMSException ex) { + throw new JmsTransportException("Could not send request message", ex); + } + finally { + try { + if (sender != null) { + sender.close(); + } + } + catch (JMSException ex) { + throw new JmsTransportException("Could not close QueueSender", ex); + } + } + } + + protected boolean hasResponse() throws IOException { + if (responseMessage != null) { + return true; + } + else if (responseQueue != null) { + QueueReceiver receiver = null; + try { + receiver = session.createReceiver(responseQueue); + responseMessage = (BytesMessage) receiver.receive(receiveTimeout); + return responseMessage != null; + } + catch (JMSException ex) { + throw new JmsTransportException("Could not receive message", ex); + } + finally { + try { + if (receiver != null) { + receiver.close(); + } + } + catch (JMSException ex) { + throw new JmsTransportException("Could not close QueueReceiver", ex); + } + try { + responseQueue.delete(); + responseQueue = null; + } + catch (JMSException ex) { + throw new JmsTransportException("Could not delete temporary response queue", ex); + } + } + } + else { + return false; + } + } + + protected Iterator getResponseHeaderNames() throws IOException { + try { + return new EnumerationIterator(responseMessage.getPropertyNames()); + } + catch (JMSException ex) { + throw new JmsTransportException("Could not get property names", ex); + } + } + + protected Iterator getResponseHeaders(String name) throws IOException { + try { + String value = responseMessage.getStringProperty(name); + return Collections.singletonList(value).iterator(); + } + catch (JMSException ex) { + throw new JmsTransportException("Could not get property value", ex); + } + } + + protected InputStream getResponseInputStream() throws IOException { + return new BytesMessageInputStream(responseMessage); + } +} diff --git a/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsTransportInputStream.java b/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsTransportInputStream.java deleted file mode 100644 index 1cb8919a..00000000 --- a/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsTransportInputStream.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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 java.io.IOException; -import java.io.InputStream; -import java.util.Collections; -import java.util.Iterator; -import javax.jms.BytesMessage; -import javax.jms.JMSException; -import javax.jms.MessageEOFException; - -import org.springframework.util.Assert; -import org.springframework.ws.transport.TransportInputStream; -import org.springframework.ws.transport.support.EnumerationIterator; - -/** - * JMS specific implementation of the TransportInputStream interface. Exposes a JMS - * BytesMessage. - * - * @author Arjen Poutsma - * @see #getMessage() - */ -class JmsTransportInputStream extends TransportInputStream { - - private final BytesMessage message; - - /** - * Constructs a new instance of the JmsTransportInputStream using the provided JMS - * BytesMessage. - * - * @param message the JMS message - */ - public JmsTransportInputStream(BytesMessage message) { - Assert.notNull(message, "message must not be null"); - this.message = message; - } - - /** - * Returns the wrapped JMS message. - */ - public BytesMessage getMessage() { - return message; - } - - protected InputStream createInputStream() throws IOException { - return new BytesMessageInputStream(); - } - - public Iterator getHeaderNames() throws IOException { - try { - return new EnumerationIterator(message.getPropertyNames()); - } - catch (JMSException ex) { - throw new JmsTransportException("Could not get property names", ex); - } - } - - public Iterator getHeaders(String name) throws IOException { - try { - String value = message.getStringProperty(name); - return Collections.singletonList(value).iterator(); - } - catch (JMSException ex) { - throw new JmsTransportException("Could not get property value", ex); - } - } - - /** - * InputStream that wraps the JMS BytesMessage. - */ - private class BytesMessageInputStream extends InputStream { - - 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); - } - } - } -} diff --git a/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsTransportOutputStream.java b/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsTransportOutputStream.java deleted file mode 100644 index 586789da..00000000 --- a/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsTransportOutputStream.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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 java.io.IOException; -import java.io.OutputStream; -import javax.jms.BytesMessage; -import javax.jms.JMSException; -import javax.jms.Session; - -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; -import org.springframework.ws.transport.TransportOutputStream; - -/** - * JMS specific implementation of the TransportOutputStream interface. Exposes a JMS - * BytesMessage, constructed lazily using a Session. - * - * @author Arjen Poutsma - * @see #getMessage() - */ -class JmsTransportOutputStream extends TransportOutputStream { - - private BytesMessage message; - - private final Session session; - - private String correlationId; - - /** - * Constructs a new instance of the JmsTransportOutputStream with the given session. - * - * @param session the JMS session - * @see javax.jms.Message#setJMSCorrelationID(String) - */ - public JmsTransportOutputStream(Session session) { - this(session, null); - } - - /** - * Constructs a new instance of the JmsTransportOutputStream with the given session and correlation ID. - * The correlation ID is used for creating a response to a request JMS message. - * - * @param session the JMS session - * @param correlationId the correlation id - * @see javax.jms.Message#setJMSCorrelationID(String) - */ - public JmsTransportOutputStream(Session session, String correlationId) { - Assert.notNull(session, "session must not be null"); - this.session = session; - this.correlationId = correlationId; - } - - /** - * Returns the wrapped JMS Session. - */ - public Session getSession() { - return session; - } - - /** - * Returns the wrapped JMS BytesMessage. Created lazily. - */ - public BytesMessage getMessage() throws IOException { - if (message == null) { - try { - message = session.createBytesMessage(); - if (StringUtils.hasLength(correlationId)) { - message.setJMSCorrelationID(correlationId); - } - } - catch (JMSException ex) { - throw new JmsTransportException("Could not create message", ex); - } - } - return message; - } - - protected OutputStream createOutputStream() throws IOException { - return new BytesMessageOutputStream(); - } - - public void addHeader(String name, String value) throws IOException { - try { - getMessage().setStringProperty(name, value); - } - catch (JMSException ex) { - throw new JmsTransportException("Could not set property", ex); - } - } - - /** - * OutputStream that wraps the JMS BytesMessage. - */ - private class BytesMessageOutputStream extends OutputStream { - - public void write(byte b[]) throws IOException { - try { - getMessage().writeBytes(b); - } - catch (JMSException ex) { - throw new JmsTransportException(ex); - } - } - - public void write(byte b[], int off, int len) throws IOException { - try { - getMessage().writeBytes(b, off, len); - } - catch (JMSException ex) { - throw new JmsTransportException(ex); - } - } - - public void write(int b) throws IOException { - try { - getMessage().writeByte((byte) b); - } - catch (JMSException ex) { - throw new JmsTransportException(ex); - } - } - } - -} diff --git a/sandbox/src/main/java/org/springframework/ws/transport/jms/support/JmsWebServiceMessageReceiverObjectSupport.java b/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsWebServiceMessageReceiverObjectSupport.java similarity index 52% rename from sandbox/src/main/java/org/springframework/ws/transport/jms/support/JmsWebServiceMessageReceiverObjectSupport.java rename to sandbox/src/main/java/org/springframework/ws/transport/jms/JmsWebServiceMessageReceiverObjectSupport.java index 5ed9cb18..14c98bad 100644 --- a/sandbox/src/main/java/org/springframework/ws/transport/jms/support/JmsWebServiceMessageReceiverObjectSupport.java +++ b/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsWebServiceMessageReceiverObjectSupport.java @@ -14,20 +14,14 @@ * limitations under the License. */ -package org.springframework.ws.transport.jms.support; +package org.springframework.ws.transport.jms; import javax.jms.BytesMessage; import javax.jms.Message; -import javax.jms.MessageProducer; import javax.jms.Session; -import org.springframework.jms.support.JmsUtils; -import org.springframework.ws.WebServiceMessage; -import org.springframework.ws.transport.TransportInputStream; -import org.springframework.ws.transport.TransportOutputStream; +import org.springframework.ws.transport.WebServiceConnection; import org.springframework.ws.transport.WebServiceMessageReceiver; -import org.springframework.ws.transport.jms.JmsTransportInputStream; -import org.springframework.ws.transport.jms.JmsTransportOutputStream; import org.springframework.ws.transport.support.SimpleWebServiceMessageReceiverObjectSupport; /** @@ -37,7 +31,7 @@ import org.springframework.ws.transport.support.SimpleWebServiceMessageReceiverO * This class can be used as a base for a EJB MessageDrivenBean, or using Spring-2.0's MessageDriven POJO's. * * @author Arjen Poutsma - * @see #handle(javax.jms.Message,javax.jms.Session) + * @see #handleMessage(javax.jms.Message,javax.jms.Session) */ public abstract class JmsWebServiceMessageReceiverObjectSupport extends SimpleWebServiceMessageReceiverObjectSupport { @@ -48,35 +42,15 @@ public abstract class JmsWebServiceMessageReceiverObjectSupport extends SimpleWe * @param session the JMS session used to create a response * @throws IllegalArgumentException when request is not a BytesMessage */ - protected final void handle(Message request, Session session) throws Exception { + protected final void handleMessage(Message request, Session session) throws Exception { if (request instanceof BytesMessage) { - TransportInputStream tis = new JmsTransportInputStream((BytesMessage) request); - TransportOutputStream tos = new JmsTransportOutputStream(session, request.getJMSCorrelationID()); - handle(tis, tos); + WebServiceConnection connection = new JmsReceivingWebServiceConnection((BytesMessage) request, session); + handleConnection(connection, getMessageReceiver()); } else { throw new IllegalArgumentException( - "Wrong message type: [" + request.getClass() + "]. Only BytesMessages can be handled"); + "Wrong message type: [" + request.getClass() + "]. Only BytesMessages can be handled."); } } - - protected final void handleResponse(TransportInputStream tis, TransportOutputStream tos, WebServiceMessage response) - throws Exception { - Message requestMessage = ((JmsTransportInputStream) tis).getMessage(); - if (requestMessage.getJMSReplyTo() == null) { - logger.warn("Incoming message has no ReplyTo set, not sending response"); - return; - } - response.writeTo(tos); - Session session = ((JmsTransportOutputStream) tos).getSession(); - MessageProducer producer = session.createProducer(requestMessage.getJMSReplyTo()); - Message responseMessage = ((JmsTransportOutputStream) tos).getMessage(); - try { - producer.send(responseMessage); - } - finally { - JmsUtils.closeMessageProducer(producer); - } - } } diff --git a/sandbox/src/main/java/org/springframework/ws/transport/jms/MessageEndpointMessageListener.java b/sandbox/src/main/java/org/springframework/ws/transport/jms/WebServiceMessageReceiverMessageListener.java similarity index 62% rename from sandbox/src/main/java/org/springframework/ws/transport/jms/MessageEndpointMessageListener.java rename to sandbox/src/main/java/org/springframework/ws/transport/jms/WebServiceMessageReceiverMessageListener.java index 3fda3085..f08bc295 100644 --- a/sandbox/src/main/java/org/springframework/ws/transport/jms/MessageEndpointMessageListener.java +++ b/sandbox/src/main/java/org/springframework/ws/transport/jms/WebServiceMessageReceiverMessageListener.java @@ -22,27 +22,26 @@ import javax.jms.Message; import javax.jms.Session; import org.springframework.jms.listener.SessionAwareMessageListener; -import org.springframework.ws.transport.jms.support.JmsWebServiceMessageReceiverObjectSupport; +import org.springframework.ws.WebServiceMessage; +import org.springframework.ws.WebServiceMessageFactory; +import org.springframework.ws.transport.WebServiceMessageReceiver; /** - * Spring-2.0 SessionAwareMessageListener that can be used to handle incoming JMS messages. Requires a - * WebServiceMessageFactory which is used to convert the incoming JMS TextMessage into a - * WebServiceMessage, and passes that context to the required MessageEndpoint. If a response - * is created, it is sent using a response JMS message. - *

- * Note that the MessageDispatcher implements the MessageEndpoint interface, enabling this - * adapter to function as a gateway to further message handling logic. + * 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 + * messageReceiver. If a response is created, it is sent using a response JMS message. * * @author Arjen Poutsma * @see #setMessageFactory(org.springframework.ws.WebServiceMessageFactory) * @see #setMessageReceiver(org.springframework.ws.transport.WebServiceMessageReceiver) */ -public class MessageEndpointMessageListener extends JmsWebServiceMessageReceiverObjectSupport +public class WebServiceMessageReceiverMessageListener extends JmsWebServiceMessageReceiverObjectSupport implements SessionAwareMessageListener { public void onMessage(Message message, Session session) throws JMSException { try { - handle((BytesMessage) message, session); + handleMessage(message, session); } catch (Exception ex) { JMSException jmsException = new JMSException(ex.getMessage()); diff --git a/sandbox/src/main/resources/org/springframework/ws/transport/jms/applicationContext-ws-jms.xml b/sandbox/src/main/resources/org/springframework/ws/transport/jms/applicationContext-ws-jms.xml index 8e036e15..26f8f54b 100644 --- a/sandbox/src/main/resources/org/springframework/ws/transport/jms/applicationContext-ws-jms.xml +++ b/sandbox/src/main/resources/org/springframework/ws/transport/jms/applicationContext-ws-jms.xml @@ -28,7 +28,7 @@ - + Spring 2.0 SessionAwareMessageListener that creates a SOAP message from the invoming JMS message using a messageFactory, and forwards it to the message to the messageDispatcher. Both of these beans are defined diff --git a/sandbox/src/test/java/org/springframework/ws/transport/jms/JmsMessageSenderIntegrationTest.java b/sandbox/src/test/java/org/springframework/ws/transport/jms/JmsMessageSenderIntegrationTest.java new file mode 100644 index 00000000..029eb97e --- /dev/null +++ b/sandbox/src/test/java/org/springframework/ws/transport/jms/JmsMessageSenderIntegrationTest.java @@ -0,0 +1,143 @@ +/* + * 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 java.util.Iterator; +import javax.jms.BytesMessage; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.Session; + +import org.springframework.jms.core.JmsTemplate; +import org.springframework.jms.core.MessageCreator; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; +import org.springframework.util.FileCopyUtils; +import org.springframework.ws.transport.TransportInputStream; +import org.springframework.ws.transport.TransportOutputStream; +import org.springframework.ws.transport.WebServiceConnection; + +public class JmsMessageSenderIntegrationTest extends AbstractDependencyInjectionSpringContextTests { + + private static final String REQUEST_HEADER_NAME = "RequestHeader"; + + private static final String REQUEST_HEADER_VALUE = "RequestHeaderValue"; + + private static final String RESPONSE_HEADER_NAME = "ResponseHeader"; + + private static final String RESPONSE_HEADER_VALUE = "ResponseHeaderValue"; + + private static final String REQUEST = "Request"; + + private static final String RESPONSE = "Response"; + + private JmsMessageSender messageSender; + + private JmsTemplate jmsTemplate; + + public void setMessageSender(JmsMessageSender messageSender) { + this.messageSender = messageSender; + } + + public void setJmsTemplate(JmsTemplate jmsTemplate) { + this.jmsTemplate = jmsTemplate; + } + + protected String[] getConfigLocations() { + return new String[]{"classpath:org/springframework/ws/transport/jms/jms-sender-applicationContext.xml"}; + } + + public void testSendAndReceiveNoResponse() throws Exception { + WebServiceConnection wsConnection = null; + try { + wsConnection = messageSender.createConnection(); + TransportOutputStream tos = wsConnection.getTransportOutputStream(); + tos.addHeader("Content-Type", "text/xml"); + tos.addHeader(REQUEST_HEADER_NAME, REQUEST_HEADER_VALUE); + FileCopyUtils.copy(REQUEST.getBytes("UTF-8"), tos); + + BytesMessage request = (BytesMessage) jmsTemplate.receive(); + assertEquals("Invalid header value received on server side", REQUEST_HEADER_VALUE, + request.getStringProperty(REQUEST_HEADER_NAME)); + assertEquals("Invalid request received", REQUEST, getMessageContents(request)); + assertNull("Response", wsConnection.getTransportInputStream()); + } + finally { + if (wsConnection != null) { + wsConnection.close(); + } + } + } + + public void testSendAndReceiveResponse() throws Exception { + WebServiceConnection wsConnection = null; + try { + wsConnection = messageSender.createConnection(); + TransportOutputStream tos = wsConnection.getTransportOutputStream(); + tos.addHeader("Content-Type", "text/xml"); + tos.addHeader(REQUEST_HEADER_NAME, REQUEST_HEADER_VALUE); + FileCopyUtils.copy(REQUEST.getBytes("UTF-8"), tos); + + BytesMessage request = (BytesMessage) jmsTemplate.receive(); + assertEquals("Invalid header value received on server side", REQUEST_HEADER_VALUE, + request.getStringProperty(REQUEST_HEADER_NAME)); + assertEquals("Invalid request received", REQUEST, getMessageContents(request)); + final byte[] bytes = RESPONSE.getBytes("UTF-8"); + jmsTemplate.send(request.getJMSReplyTo(), new MessageCreator() { + public Message createMessage(Session session) throws JMSException { + BytesMessage response = session.createBytesMessage(); + response.setStringProperty(RESPONSE_HEADER_NAME, RESPONSE_HEADER_VALUE); + response.writeBytes(bytes); + return response; + } + }); + assertNotNull("No response", wsConnection.getTransportInputStream()); + TransportInputStream tis = wsConnection.getTransportInputStream(); + boolean headerFound = false; + for (Iterator iterator = tis.getHeaderNames(); iterator.hasNext();) { + String headerName = (String) iterator.next(); + if (RESPONSE_HEADER_NAME.equals(headerName)) { + headerFound = true; + } + } + assertTrue("Response has invalid header", headerFound); + Iterator headerValues = tis.getHeaders(RESPONSE_HEADER_NAME); + assertTrue("Response has no header values", headerValues.hasNext()); + assertEquals("Response has invalid header values", RESPONSE_HEADER_VALUE, headerValues.next()); + String result = new String(FileCopyUtils.copyToByteArray(tis), "UTF-8"); + assertEquals("Invalid response", RESPONSE, result); + } + finally { + if (wsConnection != null) { + wsConnection.close(); + } + } + } + + private String getMessageContents(BytesMessage message) throws JMSException, IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int bytesRead = -1; + while ((bytesRead = message.readBytes(buffer)) != -1) { + out.write(buffer, 0, bytesRead); + } + out.flush(); + return out.toString("UTF-8"); + } + +} \ No newline at end of file diff --git a/sandbox/src/test/java/org/springframework/ws/transport/jms/JmsTransportInputStreamTest.java b/sandbox/src/test/java/org/springframework/ws/transport/jms/JmsTransportInputStreamTest.java deleted file mode 100644 index de71095f..00000000 --- a/sandbox/src/test/java/org/springframework/ws/transport/jms/JmsTransportInputStreamTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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 java.util.Collections; -import java.util.Iterator; -import javax.jms.BytesMessage; - -import junit.framework.TestCase; -import org.easymock.MockControl; - -public class JmsTransportInputStreamTest extends TestCase { - - private JmsTransportInputStream tis; - - private MockControl messageControl; - - private BytesMessage messageMock; - - protected void setUp() throws Exception { - messageControl = MockControl.createControl(BytesMessage.class); - messageMock = (BytesMessage) messageControl.getMock(); - tis = new JmsTransportInputStream(messageMock); - } - - public void testHeaders() throws Exception { - String headerName = "Header"; - messageControl.expectAndReturn(messageMock.getPropertyNames(), - Collections.enumeration(Collections.singleton(headerName))); - String headerValue = "Value"; - messageControl.expectAndReturn(messageMock.getStringProperty(headerName), headerValue); - messageControl.replay(); - Iterator iterator = tis.getHeaderNames(); - assertTrue("No headers found", iterator.hasNext()); - assertEquals("Invalid header", headerName, iterator.next()); - iterator = tis.getHeaders(headerName); - assertTrue("No header values found", iterator.hasNext()); - assertEquals("Invalid header value", headerValue, iterator.next()); - messageControl.verify(); - } - -} \ No newline at end of file diff --git a/sandbox/src/test/java/org/springframework/ws/transport/jms/JmsTransportOutputStreamTest.java b/sandbox/src/test/java/org/springframework/ws/transport/jms/JmsTransportOutputStreamTest.java deleted file mode 100644 index daa1ac5e..00000000 --- a/sandbox/src/test/java/org/springframework/ws/transport/jms/JmsTransportOutputStreamTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.Session; - -import junit.framework.TestCase; -import org.easymock.MockControl; - -public class JmsTransportOutputStreamTest extends TestCase { - - private JmsTransportOutputStream tos; - - private MockControl messageControl; - - private BytesMessage messageMock; - - private MockControl sessionControl; - - private Session sessionMock; - - protected void setUp() throws Exception { - messageControl = MockControl.createControl(BytesMessage.class); - messageMock = (BytesMessage) messageControl.getMock(); - sessionControl = MockControl.createControl(Session.class); - sessionMock = (Session) sessionControl.getMock(); - tos = new JmsTransportOutputStream(sessionMock); - } - - public void testHeaders() throws Exception { - sessionControl.expectAndReturn(sessionMock.createBytesMessage(), messageMock); - String headerName = "Header"; - String headerValue = "Value"; - messageMock.setStringProperty(headerName, headerValue); - sessionControl.replay(); - messageControl.replay(); - tos.addHeader(headerName, headerValue); - sessionControl.verify(); - messageControl.verify(); - } - -} \ No newline at end of file diff --git a/sandbox/src/test/java/org/springframework/ws/transport/jms/MessageEndpointMessageListenerTest.java b/sandbox/src/test/java/org/springframework/ws/transport/jms/MessageEndpointMessageListenerTest.java index 8c16e84f..2960f5f3 100644 --- a/sandbox/src/test/java/org/springframework/ws/transport/jms/MessageEndpointMessageListenerTest.java +++ b/sandbox/src/test/java/org/springframework/ws/transport/jms/MessageEndpointMessageListenerTest.java @@ -41,7 +41,7 @@ public class MessageEndpointMessageListenerTest extends TestCase { " \n" + " DIS\n" + " \n" + " \n" + ""; - private MessageEndpointMessageListener messageListener; + private WebServiceMessageReceiverMessageListener messageListener; private BytesMessage request; @@ -50,7 +50,7 @@ public class MessageEndpointMessageListenerTest extends TestCase { private Session sessionMock; protected void setUp() throws Exception { - messageListener = new MessageEndpointMessageListener(); + messageListener = new WebServiceMessageReceiverMessageListener(); request = new ActiveMQBytesMessage(); request.writeBytes(REQUEST.getBytes("UTF-8")); messageListener.setMessageFactory(new MockWebServiceMessageFactory()); diff --git a/sandbox/src/test/java/org/springframework/ws/transport/jms/SimpleTestingMessageReceiver.java b/sandbox/src/test/java/org/springframework/ws/transport/jms/SimpleTestingMessageReceiver.java new file mode 100644 index 00000000..7597d253 --- /dev/null +++ b/sandbox/src/test/java/org/springframework/ws/transport/jms/SimpleTestingMessageReceiver.java @@ -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.jms; + +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); + Transformer transformer = createTransformer(); + transformer.transform(messageContext.getRequest().getPayloadSource(), + messageContext.getResponse().getPayloadResult()); + } +} diff --git a/sandbox/src/test/java/org/springframework/ws/transport/jms/WebServiceMessageReceiverMessageListenerIntegrationTest.java b/sandbox/src/test/java/org/springframework/ws/transport/jms/WebServiceMessageReceiverMessageListenerIntegrationTest.java new file mode 100644 index 00000000..51f96784 --- /dev/null +++ b/sandbox/src/test/java/org/springframework/ws/transport/jms/WebServiceMessageReceiverMessageListenerIntegrationTest.java @@ -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; + +import java.io.IOException; +import javax.jms.BytesMessage; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.Queue; +import javax.jms.Session; + +import org.springframework.jms.core.JmsTemplate; +import org.springframework.jms.core.MessageCreator; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +/** @author Arjen Poutsma */ +public class WebServiceMessageReceiverMessageListenerIntegrationTest + extends AbstractDependencyInjectionSpringContextTests { + + private static final String CONTENT = + "" + "\n" + + "\n" + + "DIS\n" + "\n" + ""; + + private JmsTemplate jmsTemplate; + + private Queue responseQueue; + + public void setJmsTemplate(JmsTemplate jmsTemplate) { + this.jmsTemplate = jmsTemplate; + } + + 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 testIt() throws JMSException, IOException { + final byte[] b = CONTENT.getBytes("UTF-8"); + jmsTemplate.send(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); + } + +} diff --git a/sandbox/src/test/resources/org/springframework/ws/transport/jms/jms-receiver-applicationContext.xml b/sandbox/src/test/resources/org/springframework/ws/transport/jms/jms-receiver-applicationContext.xml new file mode 100644 index 00000000..e0ee3660 --- /dev/null +++ b/sandbox/src/test/resources/org/springframework/ws/transport/jms/jms-receiver-applicationContext.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sandbox/src/test/resources/org/springframework/ws/transport/jms/jms-sender-applicationContext.xml b/sandbox/src/test/resources/org/springframework/ws/transport/jms/jms-sender-applicationContext.xml new file mode 100644 index 00000000..7359a7dd --- /dev/null +++ b/sandbox/src/test/resources/org/springframework/ws/transport/jms/jms-sender-applicationContext.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file