package org.yajul.jms;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yajul.jta.JtaHelper;
import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.jms.Topic;
import javax.transaction.UserTransaction;
import javax.naming.InitialContext;
import java.io.Serializable;
import java.util.Iterator;
import java.util.Map;
import org.yajul.util.Callable;
/**
* Generic message sender.
* <br>User: Joshua Davis
* Date: Sep 18, 2007
* Time: 7:06:18 AM
*/
public class MessageSender extends Endpoint {
private static Logger log = LoggerFactory.getLogger(MessageSender.class);
private int mode = DeliveryMode.PERSISTENT;
private int priority = 4;
private long ttl = 30000L;
private static final long REPLY_TIMEOUT = 5000;
private long replyTimeout = REPLY_TIMEOUT;
public MessageSender(InitialContext ic, String factoryJndiName, String destinationName, String messageSelector) {
super(ic, factoryJndiName, destinationName, messageSelector);
}
public MessageSender(InitialContext ic, String factoryJndiName, Destination destination, String messageSelector) {
super(ic, factoryJndiName, destination, messageSelector);
}
@Override
protected void onConnectionCreated(Connection connection) throws JMSException {
connection.start();
}
public long getReplyTimeout() {
return replyTimeout;
}
public void setReplyTimeout(long replyTimeout) {
this.replyTimeout = replyTimeout;
}
public ObjectMessage createObjectMessage() {
try {
Session session = getSession();
return session.createObjectMessage();
}
catch (JMSException e) {
throw new RuntimeException(e);
}
}
public void send(Message message) {
try {
MessageProducer sender = getProducer();
sender.setDeliveryMode(mode);
sender.setPriority(priority);
sender.setTimeToLive(ttl);
sender.send(message);
}
catch (JMSException e) {
throw new RuntimeException(e);
}
}
public Topic createTemporaryTopic() {
try {
return getSession().createTemporaryTopic();
}
catch (JMSException e) {
throw new RuntimeException(e);
}
}
public Message sendAndWaitForReply(Message msg, UserTransaction ut) {
Topic replyto;
MessageConsumer consumer = null;
Message reply = null;
try {
replyto = createTemporaryTopic();
consumer = getSession().createConsumer(replyto);
msg.setJMSReplyTo(replyto);
final Message m = msg;
JtaHelper.doInTx(
ut,
new Callable<Object>() {
public Object call() {
send(m);
return null;
}
});
long start = System.currentTimeMillis();
reply = consumer.receive(replyTimeout);
if (reply == null)
throw new RuntimeException("Timed out waiting for reply.");
if (log.isDebugEnabled())
log.debug("sendAndWaitForReply() : Received reply after " +
(System.currentTimeMillis() - start) + "ms");
}
catch (JMSException e) {
throw new RuntimeException(e);
}
finally {
JmsHelper.close(consumer, null, null);
}
return reply;
}
public void sendObjectMessage(Serializable object) {
sendObjectMessage(object, null);
}
public void sendObjectMessage(Serializable object, Map<String, Object> properties) {
try {
Session session = getSession();
ObjectMessage objectMessage;
objectMessage = session.createObjectMessage(object);
if (properties != null) {
Iterator<String> keys = properties.keySet().iterator();
//noinspection WhileLoopReplaceableByForEach
while (keys.hasNext()) {
String key = keys.next();
Object value = properties.get(key);
//Add the other types here if needed.
if (value instanceof Long) {
objectMessage.setLongProperty(key, (Long) value);
} else if (value instanceof String) {
objectMessage.setStringProperty(key, (String) value);
} else {
objectMessage.setObjectProperty(key, value);
}
}
}
send(objectMessage);
}
catch (JMSException e) {
throw new RuntimeException(e);
}
}
public static void sendReply(InitialContext ic, String factoryJndiName, Message message, Serializable replyObject) {
sendReply(ic, factoryJndiName, message, replyObject, null);
}
public static void sendReply(final InitialContext ic, final String factoryJndiName, Message message, Serializable replyObject, Map<String, Object> properties) {
final Destination jmsReplyTo = JmsHelper.getReplyTo(message);
if (jmsReplyTo != null) {
sendObject(new SenderFactory() {
public MessageSender createSender() {
return new MessageSender(ic, factoryJndiName, jmsReplyTo, null);
}
}, replyObject, properties);
}
}
public static void closeSender(MessageSender sender) {
if (sender != null) {
try {
sender.close();
}
catch (Exception e) {
log.error("Error while closing sender: " + e, e);
}
}
}
private static void sendObject(SenderFactory senderFactory, Serializable messageObject,
Map<String, Object> properties) {
MessageSender sender = null;
try {
sender = senderFactory.createSender();
if (properties == null)
sender.sendObjectMessage(messageObject);
else
sender.sendObjectMessage(messageObject, properties);
}
catch (Exception e) {
log.warn("Unable to send message due to: " + e, e);
}
finally {
closeSender(sender);
}
}
public static void sendObject(
final InitialContext ic, final String factoryJndiName,
final String destinationName,
Serializable messageObject) {
sendObject(ic, factoryJndiName, destinationName, messageObject, null);
}
public static void sendObject(
final InitialContext ic,
final String factoryJndiName,
final String destinationName,
Serializable messageObject,
Map<String, Object> properties) {
sendObject(new SenderFactory() {
public MessageSender createSender() {
return new MessageSender(ic, factoryJndiName, destinationName, null);
}
}, messageObject, properties);
}
public interface SenderFactory {
MessageSender createSender();
}
}