Правильное использование связи JMS-Topic

Я хочу использовать JMS (Topic) в моем проекте JavaEE 6. У меня есть один класс, который действует как издатель и подписчик темы одновременно. В следующем коде показаны наиболее важные части класса.

public class MessageHandler implements MessageListener {
    private static TopicConnectionFactory factory;
    private static Topic topic;

    private TopicSubscriber subscriber;
    private TopicPublisher publisher;

    public MessageHandler() throws NamingException, JMSException {
            if (factory == null) {
                Context context = new InitialContext();
                factory = (TopicConnectionFactory) new InitialContext()
                        .lookup("jms/myfactory");
                topic = (Topic) context.lookup("jms/mytopic");
            }
            TopicConnection connection = factory.createTopicConnection();
            connection.start();
            TopicSession session = connection
                    .createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
            subscriber = session.createSubscriber(topic);
        }

    @Override
    public void onMessage(Message message) {
        try {
            ObjectMessage msg = (ObjectMessage) message;
            Object someO=  msg.getObject();
            System.out.println(this + " receives "+someO);
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }

    public void sendMessage(Object someO) {
        try {
            ObjectMessage msg = session.createObjectMessage();
            msg.setObject(someO);
            publisher = session.createPublisher(topic);
         publisher.publish(msg);
         publisher.close();
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }     
}

Мой вопрос: хороший ли это способ создать такой класс? Моя идея заключалась в том, чтобы поделиться одним подключением и сеансом как для подписки, так и для публикации. Но я боюсь, что это может привести к накладным расходам или блокировке, потому что я не закрываю соединение, сеанс, подписчика и издателя, пока объект больше не понадобится. Все примеры, которые я нашел в Интернете, закрывают все сразу после отправки или получения сообщения ...

Заранее спасибо!


person user1727072    schedule 11.03.2013    source источник


Ответы (1)


Почему вы хотите, чтобы класс был подписчиком и издателем одновременно?

Всякий раз, используя систему обмена сообщениями, вы можете действовать как и то, и другое, но зачем вам делать это для одной и той же темы, ведь вы точно не хотите получать свои собственные сообщения?

Итак, цель темы состоит в том, чтобы использовать ее в нескольких частях приложения или в нескольких приложениях - одно помещает сообщение в тему, а другие получают сообщение, на которое они подписаны.

И это также объясняет то, что вы видели в примерах - обработка сообщений выполняется один раз, поэтому соединение может быть закрыто впоследствии.

Между прочим, поскольку вы задаете этот вопрос в области «java-ee 6» - нельзя ли использовать bean-компонент, управляемый сообщениями, аннотировать конфигурацию темы и позволить серверу приложений выполнять часть инфраструктуры за вас?

person Alexander Rühl    schedule 13.03.2013
comment
Издатель не будет получать свои собственные сообщения, так как я могу использовать метод session.createSubscriber (тема, фильтр, noLocal) и установить для параметра noLocal значение true. Выдержка из javadoc: в некоторых случаях соединение может как публиковать, так и подписываться на тему. Атрибут подписчика NoLocal позволяет подписчику запрещать доставку сообщений, опубликованных через его собственное соединение. Значение по умолчанию для этого атрибута - false. Также этот дизайн лучше всего подходит для моего случая использования. Но на самом деле я изменил одну вещь: при каждом вызове sendMessage создается и закрывается издатель. - person user1727072; 13.03.2013
comment
и вы правы с bean-компонентом, управляемым сообщениями. Я изменю это в своем приложении. - person user1727072; 13.03.2013