Introdução ao Spring JMS

Introdução ao Spring JMS

1. Visão geral

O Spring fornece uma estrutura de Integração JMS que simplifica o uso da API JMS. Este artigo apresenta os conceitos básicos dessa integração.

2. Dependência do Maven

Para usar Spring JMS em nosso aplicativo, precisamos adicionar os artefatos necessários empom.xml:


    org.springframework
    spring-jms
    4.3.3.RELEASE

A versão mais recente do artefato pode serfound here.

3. OJmsTemplate

A classeJmsTemplate trata da criação e liberação de recursos ao enviar ou receber mensagens de forma síncrona.

Portanto, a classe que usa esseJmsTemplate só precisa implementar interfaces de retorno de chamada conforme especificado na definição do método.

A partir do Spring 4.1, oJmsMessagingTemplate é construído em cima deJmsTemplate que fornece uma integração com a abstração de mensagens, ou seja,org.springframework.messaging.Message. Isso, por sua vez, nos permite criar uma mensagem para enviar de forma genérica.

4. Gerenciamento de Conexão

Para conectar e poder enviar / receber mensagens, precisamos configurar umConnectionFactory.

A ConnectionFactory is one of the JMS administered objects which are preconfigured by an administrator. Um cliente com a ajuda da configuração fará a conexão com um provedor JMS.

Spring fornece 2 tipos deConnectionFactory:

  • SingleConnectionFactory – é uma implementação da interfaceConnectionFactory, que retornará a mesma conexão em todas as chamadascreateConnection () e ignorará as chamadas paraclose ()

  • CachingConnectionFactory estende a funcionalidade deSingleConnectionFactorye adiciona o aprimora com um armazenamento em cache deSessions,MessageProducers eMessageConsumers

5. Gestão de Destino

Conforme discutido acima, junto comConnectionFactory, os destinos também são objetos administrados por JMS e podem ser armazenados e recuperados de um JNDI.

Spring fornece resolvedores genéricos comoDynamicDestinationResolvere resolvedores específicos comoJndiDestinationResolver.

OJmsTemplate delegará a resolução do nome de destino a uma das implementações com base em nossa seleção.

Ele também fornecerá uma propriedade chamadadefaultDestination - que será usada com operaçõessendereceive que não se referem a um destino específico.

6. Conversão de Mensagem

O Spring JMS estaria incompleto sem o suporte dos Conversores de Mensagens.

A estratégia de conversão padrão usada porJmsTemplate para as operaçõesConvertAndSend()eReceiveAndConvert() é a classeSimpleMessageConverter.

The SimpleMessageConverter é capaz de lidar comTextMessages,BytesMessages,MapMessages eObjectMessages. Esta classe implementa a interfaceMessageConverter.

Além deSimpleMessageConverter, Spring JMS fornece algumas outras classesMessageConverter prontas para uso, comoMappingJackson2MessageConverter,MarshallingMessageConverter,MessagingMessageConverter.

Além disso, podemos criar uma funcionalidade de conversão de mensagem personalizada simplesmente implementando os métodostoMessage() eFromMessage() da interfaceMessageConverter.

Vejamos um exemplo de snippet de código sobre a implementação de umMessageConverter personalizado,

public class SampleMessageConverter implements MessageConverter {
    public Object fromMessage(Message message)
      throws JMSException, MessageConversionException {
        //...
    }

    public Message toMessage(Object object, Session session)
      throws JMSException, MessageConversionException {
        //...
    }
}

7. Amostra de Spring JMS

Nesta seção, veremos como usarJmsTemplate para enviar e receber mensagens.

O método padrão para enviar a mensagem éJmsTemplate.send(). Ele tem dois parâmetros principais dos quais, o primeiro parâmetro é o destino JMS e o segundo parâmetro é uma implementação deMessageCreator. The JmsTemplate usa o método de retorno de chamadaMessageCreatorcreateMessage() para construir a mensagem.

JmsTemplate.send() é bom para enviar mensagens de texto simples, mas para enviar mensagens personalizadas,JmsTemplate tem outro método chamado convertAndSend().

Podemos ver abaixo a implementação desses métodos:

public class SampleJmsMessageSender {

    private JmsTemplate jmsTemplate;
    private Queue queue;

    // setters for jmsTemplate & queue

    public void simpleSend() {
        jmsTemplate.send(queue, s -> s.createTextMessage("hello queue world"));
    }
    public void sendMessage(Employee employee) {
        System.out.println("Jms Message Sender : " + employee);
        Map map = new HashMap<>();
        map.put("name", employee.getName()); map.put("age", employee.getAge());
        jmsTemplate.convertAndSend(map);
    }
}

Abaixo está a classe de receptor de mensagem, chamada de POJO acionado por mensagem (MDP). We can see that the class SampleListener is implementing the MessageListener interface and provides the text specific implementation for the interface method onMessage().

Além do métodoonMessage(), nossa classeSampleListener também é chamada de métodoreceiveAndConvert() para receber mensagens personalizadas:

public class SampleListener implements MessageListener {

    public JmsTemplate getJmsTemplate() {
        return getJmsTemplate();
    }

    public void onMessage(Message message) {
        if (message instanceof TextMessage) {
            try {
                String msg = ((TextMessage) message).getText();
                System.out.println("Message has been consumed : " + msg);
            } catch (JMSException ex) {
                throw new RuntimeException(ex);
            }
        } else {
            throw new IllegalArgumentException("Message Error");
        }
    }

    public Employee receiveMessage() throws JMSException {
        Map map = (Map) getJmsTemplate().receiveAndConvert();
        return new Employee((String) map.get("name"), (Integer) map.get("age"));
    }
}

Vimos como implementarMessageListenere abaixo vemos a configuração no contexto do aplicativo Spring:




    
    
    

DefaultMessageListenerContainer é o contêiner de ouvinte de mensagem padrão que o Spring fornece junto com muitos outros contêineres especializados.

8. Configuração básica com anotações Java

The @JmsListener is the only annotation required to convert a method of a normal bean into a JMS listener endpoint. Spring JMS fornece muito mais anotações para facilitar a implementação do JMS.

Podemos ver algumas das classes de amostra anotadas abaixo:

@JmsListener(destination = "myDestination")
public void SampleJmsListenerMethod(Message order) { ... }

Para adicionar vários ouvintes a um único método, precisamos apenas adicionar várias anotações@JmsListener.

Precisamos adicionar a anotação@EnableJms a uma de nossas classes de configuração para suportar os métodos anotados@JmsListener:

@Configuration
@EnableJms
public class AppConfig {

    @Bean
    public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
        DefaultJmsListenerContainerFactory factory
          = new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory());
        return factory;
    }
}

9. Manipulador de erro

Também podemos configurar um manipulador de erros personalizado para o contêiner do ouvinte de mensagens.

Vamos primeiro implementar a interfaceorg.springframework.util.ErrorHandler:

@Service
public class SampleJmsErrorHandler implements ErrorHandler {

    // ... logger

    @Override
    public void handleError(Throwable t) {
        LOG.warn("In default jms error handler...");
        LOG.error("Error Message : {}", t.getMessage());
    }

}

Observe que substituímos o métodohandleError(), que simplesmente registra a mensagem de erro.

E então, precisamos fazer referência ao nosso serviço de tratamento de erros emDefaultJmsListenerConnectionFactory usando o métodosetErrorHandler():

@Bean
public DefaultJmsListenerContainerFactorybjmsListenerContainerFactory() {
    DefaultJmsListenerContainerFactory factory
      = new DefaultJmsListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory());
    factory.setErrorHandler(sampleJmsErrorHandler);
    return factory;
}

Com isso, nosso manipulador de erros configurado agora capturará todas as exceções não manipuladas e registrará a mensagem.

Opcionalmente, também podemos configurar o manipulador de erros usando as configurações XML simples, atualizando nossoappContext.xml:




    
    
    
    

10. Conclusão

Neste tutorial, discutimos a configuração e os conceitos básicos do Spring JMS. Também demos uma breve olhada nas classesJmsTemplate específicas do Spring que são usadas para enviar e receber mensagens.

Você pode encontrar a implementação do código emGitHub project.