/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.transport.jms; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.jms.BytesMessage; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageProducer; import javax.jms.Session; import javax.jms.TemporaryTopic; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jms.core.JmsTemplate; import org.springframework.jms.core.SessionCallback; import com.opengamma.transport.ByteArrayMessageReceiver; import com.opengamma.transport.ByteArrayRequestSender; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.NamedThreadPoolFactory; /** * An RPC message sender/receiver that uses JMS. * <p> * This is a simple implementation based on JMS. */ public class JmsByteArrayRequestSender extends AbstractJmsByteArraySender implements ByteArrayRequestSender { /** Logger. */ private static final Logger s_logger = LoggerFactory.getLogger(JmsByteArrayRequestSender.class); /** * The executor service. */ private final ExecutorService _executor; /** * Creates an instance associated with a destination and template. * * @param destinationName the destination name, not null * @param jmsTemplate the template, not null */ public JmsByteArrayRequestSender(final String destinationName, final JmsTemplate jmsTemplate) { this(destinationName, jmsTemplate, Executors.newCachedThreadPool(new NamedThreadPoolFactory("JMS-request"))); } /** * Creates an instance associated with a destination and template, specifying the executor to use. * * @param destinationName the destination name, not null * @param jmsTemplate the template, not null * @param executor the executor, not null */ public JmsByteArrayRequestSender(final String destinationName, final JmsTemplate jmsTemplate, final ExecutorService executor) { super(destinationName, jmsTemplate); ArgumentChecker.notNull(executor, "executor"); _executor = executor; } //------------------------------------------------------------------------- @Override public void sendRequest(final byte[] request, final ByteArrayMessageReceiver responseReceiver) { s_logger.debug("Dispatching request of size {} to destination {}", request.length, getDestinationName()); _executor.execute(new Runnable() { @Override public void run() { getJmsTemplate().execute(new SessionCallback<Object>() { @Override public Object doInJms(Session session) throws JMSException { try { final TemporaryTopic tempTopic = session.createTemporaryTopic(); s_logger.debug("Requesting response to temp topic {}", tempTopic); final byte[] bytes; final MessageConsumer consumer = session.createConsumer(tempTopic); try { final BytesMessage bytesMessage = session.createBytesMessage(); bytesMessage.writeBytes(request); bytesMessage.setJMSReplyTo(tempTopic); final Destination requestDestination = getJmsTemplate().getDestinationResolver().resolveDestinationName(session, getDestinationName(), getJmsTemplate().isPubSubDomain()); final MessageProducer producer = session.createProducer(requestDestination); try { producer.send(bytesMessage); } finally { producer.close(); } final Message response = consumer.receive(getJmsTemplate().getReceiveTimeout()); if (response == null) { // TODO UTL-37. s_logger.error("Timeout reached while waiting for a response to send to {}", responseReceiver); return null; } bytes = JmsByteArrayHelper.extractBytes(response); } finally { consumer.close(); } s_logger.debug("Dispatching response of length {}", bytes.length); responseReceiver.messageReceived(bytes); } catch (Exception ex) { // TODO UTL-37. s_logger.error("Unexpected exception while waiting for a response to send to " + responseReceiver, ex); } return null; } }, true); } }); } }