Skip to content

Commit 9376403

Browse files
committed
SWS-255
1 parent 3a83b12 commit 9376403

File tree

9 files changed

+302
-51
lines changed

9 files changed

+302
-51
lines changed

support/src/main/java/org/springframework/ws/transport/jms/JmsMessageReceiver.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,17 @@
1919
import javax.jms.BytesMessage;
2020
import javax.jms.Message;
2121
import javax.jms.Session;
22+
import javax.jms.TextMessage;
2223

2324
import org.springframework.ws.transport.WebServiceConnection;
2425
import org.springframework.ws.transport.WebServiceMessageReceiver;
2526
import org.springframework.ws.transport.support.SimpleWebServiceMessageReceiverObjectSupport;
2627

2728
/**
2829
* Convenience base class for JMS server-side transport objects. Contains a {@link WebServiceMessageReceiver}, and has
29-
* methods for handling incoming JMS {@link Message} requests.
30+
* methods for handling incoming JMS {@link BytesMessage} and {@link TextMessage} requests. Also contains a
31+
* <code>textMessageEncoding</code> property, which determines the encoding used to read from and write to
32+
* <code>TextMessages</code>. This property defaults to <code>UTF-8</code>.
3033
* <p/>
3134
* Used by {@link WebServiceMessageListener} and {@link WebServiceMessageDrivenBean}.
3235
*
@@ -35,6 +38,16 @@
3538
*/
3639
public class JmsMessageReceiver extends SimpleWebServiceMessageReceiverObjectSupport {
3740

41+
/** Default encoding used to read fromn and write to {@link TextMessage} messages. */
42+
public static final String DEFAULT_TEXT_MESSAGE_ENCODING = "UTF-8";
43+
44+
private String textMessageEncoding = DEFAULT_TEXT_MESSAGE_ENCODING;
45+
46+
/** Sets the encoding used to read from and write to {@link TextMessage} messages. Defaults to <code>UTF-8</code>. */
47+
public void setTextMessageEncoding(String textMessageEncoding) {
48+
this.textMessageEncoding = textMessageEncoding;
49+
}
50+
3851
/**
3952
* Handles an incoming message. Uses the given session to create a response message.
4053
*
@@ -43,13 +56,17 @@ public class JmsMessageReceiver extends SimpleWebServiceMessageReceiverObjectSup
4356
* @throws IllegalArgumentException when request is not a {@link BytesMessage}
4457
*/
4558
protected final void handleMessage(Message request, Session session) throws Exception {
59+
WebServiceConnection connection;
4660
if (request instanceof BytesMessage) {
47-
WebServiceConnection connection = new JmsReceiverConnection((BytesMessage) request, session);
48-
handleConnection(connection);
61+
connection = new JmsReceiverConnection((BytesMessage) request, session);
62+
}
63+
else if (request instanceof TextMessage) {
64+
connection = new JmsReceiverConnection((TextMessage) request, textMessageEncoding, session);
4965
}
5066
else {
51-
throw new IllegalArgumentException(
52-
"Wrong message type: [" + request.getClass() + "]. Only BytesMessages can be handled.");
67+
throw new IllegalArgumentException("Wrong message type: [" + request.getClass() +
68+
"]. Only BytesMessages or TextMessages can be handled.");
5369
}
70+
handleConnection(connection);
5471
}
5572
}

support/src/main/java/org/springframework/ws/transport/jms/JmsMessageSender.java

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@
2323
import javax.jms.ConnectionFactory;
2424
import javax.jms.Destination;
2525
import javax.jms.JMSException;
26+
import javax.jms.Message;
2627
import javax.jms.MessageConsumer;
2728
import javax.jms.MessageProducer;
2829
import javax.jms.Queue;
2930
import javax.jms.Session;
31+
import javax.jms.TextMessage;
3032
import javax.jms.Topic;
3133

3234
import org.springframework.jms.connection.ConnectionFactoryUtils;
@@ -38,7 +40,7 @@
3840
import org.springframework.ws.transport.jms.support.JmsTransportUtils;
3941

4042
/**
41-
* {@link WebServiceMessageSender} implementation that uses JMS {@link BytesMessage}s. Requires a JMS {@link
43+
* {@link WebServiceMessageSender} implementation that uses JMS {@link Message}s. Requires a JMS {@link
4244
* ConnectionFactory} to operate.
4345
* <p/>
4446
* This message sender supports URI's of the following format: <blockquote> <tt><b>jms:</b></tt><i>destination</i>[<tt><b>?</b></tt><i>param-name</i><tt><b>=</b></tt><i>param-value</i>][<tt><b>&amp;</b></tt><i>param-name</i><tt><b>=</b></tt><i>param-value</i>]*
@@ -49,18 +51,23 @@
4951
* <blockquote><table> <tr><th><i>param-name</i></th><th><i>Description</i></th></tr>
5052
* <tr><td><tt>deliveryMode</tt></td><td>Indicates whether the request message is persistent or not. This may be
5153
* <tt>PERSISTENT</tt> or <tt>NON_PERSISTENT</tt>. See {@link MessageProducer#setDeliveryMode(int)}</td></tr>
52-
* <tr><td><tt>timeToLive</tt></td><td>The lifetime, in milliseconds, of the request message. See {@link
53-
* MessageProducer#setTimeToLive(long)}</td></tr> <tr><td><tt>priority</tt></td><td>The JMS priority (0-9) associated
54-
* with the request message. See {@link MessageProducer#setPriority(int)}</td></tr>
55-
* <tr><td><tt>replyToName</tt></td><td>The name of the destination to which the response message must be sent, that
56-
* will be resolved by the {@link #getDestinationResolver() destination resolver}.</td></tr> </table></blockquote>
54+
* <tr><td><tt>messageType</tt></td><td>The message type. This may be <tt>BINARY_MESSAGE</tt> (the default) or
55+
* <tt>TEXT_MESSAGE</tt></td></tr> <tr><td><tt>priority</tt></td><td>The JMS priority (0-9) associated with the request
56+
* message. See {@link MessageProducer#setPriority(int)}</td></tr> <tr><td><tt>replyToName</tt></td><td>The name of the
57+
* destination to which the response message must be sent, that will be resolved by the {@link #getDestinationResolver()
58+
* destination resolver}.</td></tr> <tr><td><tt>timeToLive</tt></td><td>The lifetime, in milliseconds, of the request
59+
* message. See {@link MessageProducer#setTimeToLive(long)}</td></tr> </table></blockquote>
5760
* <p/>
5861
* If the <tt>replyToName</tt> is not set, a {@link Session#createTemporaryQueue() temporary queue} is used.
5962
* <p/>
63+
* This class uses {@link BytesMessage} messages by default, but can be configured to send {@link TextMessage} messages
64+
* instead. <b>Note</b> that <code>BytesMessages</code> are prefered, since <code>TextMessages</code> do not support
65+
* attachments and charactering encodings reliably.
66+
* <p/>
6067
* Some examples of JMS URIs are:
6168
* <p/>
6269
* <blockquote> <tt>jms:SomeQueue</tt><br> <tt>jms:SomeTopic?priority=3&deliveryMode=NON_PERSISTENT</tt><br>
63-
* <tt>jms:RequestQueue?replyToName=ResponseQueueName</tt></blockquote>
70+
* <tt>jms:RequestQueue?replyToName=ResponseQueueName</tt><br> <tt>jms:Queue?messageType=TEXT_MESSAGE</blockquote>
6471
*
6572
* @author Arjen Poutsma
6673
* @see <a href="http://www.ietf.org/internet-drafts/draft-merrick-jms-iri-00.txt">IRI Scheme for Java(tm) Message
@@ -69,18 +76,27 @@
6976
*/
7077
public class JmsMessageSender extends JmsDestinationAccessor implements WebServiceMessageSender {
7178

72-
/**
73-
* Default timeout for receive operations: -1 indicates a blocking receive without timeout.
74-
*/
79+
/** Default timeout for receive operations: -1 indicates a blocking receive without timeout. */
7580
public static final long DEFAULT_RECEIVE_TIMEOUT = -1;
7681

82+
/** Default encoding used to read fromn and write to {@link TextMessage} messages. */
83+
public static final String DEFAULT_TEXT_MESSAGE_ENCODING = "UTF-8";
84+
7785
private long receiveTimeout = DEFAULT_RECEIVE_TIMEOUT;
7886

87+
private String textMessageEncoding = DEFAULT_TEXT_MESSAGE_ENCODING;
88+
89+
/** Sets the encoding used to read from {@link TextMessage} messages. Defaults to <code>UTF-8</code>. */
90+
public void setTextMessageEncoding(String textMessageEncoding) {
91+
this.textMessageEncoding = textMessageEncoding;
92+
}
93+
7994
/**
8095
* Create a new <code>JmsMessageSender</code>
8196
* <p/>
8297
* <b>Note</b>: The ConnectionFactory has to be set before using the instance. This constructor can be used to
83-
* prepare a JmsTemplate via a BeanFactory, typically setting the ConnectionFactory via setConnectionFactory.
98+
* prepare a JmsTemplate via a BeanFactory, typically setting the ConnectionFactory via {@link
99+
* #setConnectionFactory(ConnectionFactory)}.
84100
*
85101
* @see #setConnectionFactory(ConnectionFactory)
86102
*/
@@ -119,6 +135,8 @@ public WebServiceConnection createConnection(URI uri) throws IOException {
119135
wsConnection.setReceiveTimeout(receiveTimeout);
120136
wsConnection.setResponseDestination(resolveResponseDestination(jmsSession, uri));
121137
wsConnection.setTimeToLive(JmsTransportUtils.getTimeToLive(uri));
138+
wsConnection.setMessageType(JmsTransportUtils.getMessageType(uri));
139+
wsConnection.setTextMessageEncoding(textMessageEncoding);
122140
return wsConnection;
123141
}
124142
catch (JMSException ex) {

support/src/main/java/org/springframework/ws/transport/jms/JmsReceiverConnection.java

Lines changed: 83 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,19 @@
1616

1717
package org.springframework.ws.transport.jms;
1818

19+
import java.io.ByteArrayInputStream;
20+
import java.io.ByteArrayOutputStream;
1921
import java.io.IOException;
2022
import java.io.InputStream;
2123
import java.io.OutputStream;
2224
import java.util.Collections;
2325
import java.util.Iterator;
2426
import javax.jms.BytesMessage;
2527
import javax.jms.JMSException;
28+
import javax.jms.Message;
2629
import javax.jms.MessageProducer;
2730
import javax.jms.Session;
31+
import javax.jms.TextMessage;
2832

2933
import org.springframework.jms.support.JmsUtils;
3034
import org.springframework.util.Assert;
@@ -35,37 +39,70 @@
3539

3640
/**
3741
* Implementation of {@link WebServiceConnection} that is used for server-side JMS access. Exposes a {@link
38-
* BytesMessage} request and response message.
42+
* BytesMessage} or {@link TextMessage} request and response message.
43+
* <p/>
44+
* The response message type is equal to the request message type, i.e. if a <code>BytesMessage</code> is received as
45+
* request, a <code>BytesMessage</code> is created as response, and if a <code>TextMessage</code> is received, a
46+
* <code>TextMessage</code> response is created.
3947
*
4048
* @author Arjen Poutsma
4149
* @since 1.5.0
4250
*/
4351
public class JmsReceiverConnection extends AbstractReceiverConnection {
4452

45-
private final BytesMessage requestMessage;
53+
private final Message requestMessage;
4654

4755
private final Session session;
4856

49-
private BytesMessage responseMessage;
57+
private Message responseMessage;
5058

51-
/** Constructs a new JMS connection with the given parameters. */
52-
protected JmsReceiverConnection(BytesMessage requestMessage, Session session) {
59+
private String textMessageEncoding;
60+
61+
private JmsReceiverConnection(Message requestMessage, Session session) {
5362
Assert.notNull(requestMessage, "requestMessage must not be null");
5463
Assert.notNull(session, "session must not be null");
5564
this.requestMessage = requestMessage;
5665
this.session = session;
5766
}
5867

59-
/** Returns the request message for this connection. */
60-
public BytesMessage getRequestMessage() {
68+
/**
69+
* Constructs a new JMS connection with the given {@link BytesMessage}.
70+
*
71+
* @param requestMessage the JMS request message
72+
* @param session the JMS session
73+
*/
74+
protected JmsReceiverConnection(BytesMessage requestMessage, Session session) {
75+
this((Message) requestMessage, session);
76+
}
77+
78+
/**
79+
* Constructs a new JMS connection with the given {@link TextMessage}.
80+
*
81+
* @param requestMessage the JMS request message
82+
* @param session the JMS session
83+
*/
84+
protected JmsReceiverConnection(TextMessage requestMessage, String encoding, Session session) {
85+
this(requestMessage, session);
86+
this.textMessageEncoding = encoding;
87+
}
88+
89+
/** Returns the request message for this connection. Returns either a {@link BytesMessage} or a {@link TextMessage}. */
90+
public Message getRequestMessage() {
6191
return requestMessage;
6292
}
6393

64-
/** Returns the response message, if any, for this connection. */
65-
public BytesMessage getResponseMessage() {
94+
/**
95+
* Returns the response message, if any, for this connection. Returns either a {@link BytesMessage} or a {@link
96+
* TextMessage}.
97+
*/
98+
public Message getResponseMessage() {
6699
return responseMessage;
67100
}
68101

102+
/*
103+
* Errors
104+
*/
105+
69106
public String getErrorMessage() throws IOException {
70107
return null;
71108
}
@@ -98,7 +135,20 @@ protected Iterator getRequestHeaders(String name) throws IOException {
98135
}
99136

100137
protected InputStream getRequestInputStream() throws IOException {
101-
return new BytesMessageInputStream(requestMessage);
138+
if (requestMessage instanceof BytesMessage) {
139+
return new BytesMessageInputStream((BytesMessage) requestMessage);
140+
}
141+
else {
142+
TextMessage textMessage = (TextMessage) requestMessage;
143+
try {
144+
String text = textMessage.getText();
145+
byte[] contents = text != null ? text.getBytes(textMessageEncoding) : new byte[0];
146+
return new ByteArrayInputStream(contents);
147+
}
148+
catch (JMSException ex) {
149+
throw new JmsTransportException(ex);
150+
}
151+
}
102152
}
103153

104154
/*
@@ -107,7 +157,12 @@ protected InputStream getRequestInputStream() throws IOException {
107157

108158
protected void onSendBeforeWrite(WebServiceMessage message) throws IOException {
109159
try {
110-
responseMessage = session.createBytesMessage();
160+
if (requestMessage instanceof BytesMessage) {
161+
responseMessage = session.createBytesMessage();
162+
}
163+
else {
164+
responseMessage = session.createTextMessage();
165+
}
111166
responseMessage.setJMSCorrelationID(requestMessage.getJMSMessageID());
112167
}
113168
catch (JMSException ex) {
@@ -125,7 +180,23 @@ protected void addResponseHeader(String name, String value) throws IOException {
125180
}
126181

127182
protected OutputStream getResponseOutputStream() throws IOException {
128-
return new BytesMessageOutputStream(responseMessage);
183+
if (responseMessage instanceof BytesMessage) {
184+
return new BytesMessageOutputStream((BytesMessage) responseMessage);
185+
}
186+
else {
187+
return new ByteArrayOutputStream() {
188+
189+
public void close() throws IOException {
190+
String text = new String(toByteArray(), textMessageEncoding);
191+
try {
192+
((TextMessage) responseMessage).setText(text);
193+
}
194+
catch (JMSException ex) {
195+
throw new JmsTransportException(ex);
196+
}
197+
}
198+
};
199+
}
129200
}
130201

131202
protected void onSendAfterWrite(WebServiceMessage message) throws IOException {

0 commit comments

Comments
 (0)