Search code examples
spring-boothornetq

Sending a message to an embedded HornetQ from an external application


I am using spring-boot 1.2.2.

I have an embedded hornet queue setup in application.properties:

spring.hornetq.mode=embedded
spring.hornetq.embedded.enabled=true
spring.hornetq.embedded.queues=myQueue

I want to add a message to "myQueue" from an external application (not the one with the embedded queue). Is this possible?

In the other application (the one without the embedded hornetq), I tried creating a connectionFactory that points to the embedded hornetq server but I don't really know what port I should be using. According to the spring-boot documentation it says it is only valid for "native" mode.

spring.hornetq.mode= # connection mode (native, embedded)
spring.hornetq.host=localhost # hornetQ host (native mode)
spring.hornetq.port=5445 # hornetQ port (native mode)

here is my code so far:

@EnableJms
@Configuration
public class HornetQConfig {

    @Bean
    public CachingConnectionFactory connectionFactory() {
        CachingConnectionFactory cachingConnectionFactory =
                new CachingConnectionFactory();
        cachingConnectionFactory.setSessionCacheSize(10);
        cachingConnectionFactory.setCacheProducers(false);
        cachingConnectionFactory.setTargetConnectionFactory(hornetQConnectionFactory());
        return cachingConnectionFactory;
    }

    @Bean
    public HornetQConnectionFactory hornetQConnectionFactory() {

        HornetQConnectionFactory connectionFactory =
                new HornetQConnectionFactory(false, transportConfiguration());
        return connectionFactory;
    }

    @Bean
    public TransportConfiguration transportConfiguration() {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("host", "localhost");
        map.put("port", 5445);
        TransportConfiguration configuration =
                new TransportConfiguration(
                        "org.hornetq.core.remoting.impl.netty.NettyConnectorFactory", map);
        return configuration;
    }

}

And then:

@Autowired
private JmsTemplate jmsTemplate;

@Scheduled(fixedDelay = 1000L)
public void send() {
    this.jmsTemplate.convertAndSend("myQueue", "Hello from external app");
}

But I am getting a connection problem.

Failed to create session factory; nested exception is HornetQNotConnectedException[errorType=NOT_CONNECTED message=HQ119007: Cannot connect to server(s)

Solution

  • The issue is that the embedded HornetQ server is configured with only an InVMAcceptorFactory by default. You need to add an AcceptorFactory that actually listens on a port, like NettyAcceptorFactory.

    You can use the HornetQConfigurationCustomizer to configure this. Below example uses a hardcoded host/port, but you can easily create your own properties to make this configurable.

    @Bean
    public HornetQConfigurationCustomizer hornetCustomizer() {
        return new HornetQConfigurationCustomizer() {
            @Override
            public void customize(Configuration configuration) {
                Set<TransportConfiguration> acceptors = configuration.getAcceptorConfigurations();
                Map<String, Object> params = new HashMap<String, Object>();
                params.put("host", "localhost");
                params.put("port", "5445");
                TransportConfiguration tc = new TransportConfiguration(NettyAcceptorFactory.class.getName(), params);
                acceptors.add(tc);
            }
        };
    }
    

    In your application with the embedded server, you configure it as embedded (as I believe you already have anyway, just to make sure):

    spring.hornetq.mode=embedded
    spring.hornetq.embedded.enabled=true
    spring.hornetq.embedded.queues=myQueue
    

    And in your "other" application that you want to connect to the embedded server, you configure HornetQ in native mode:

    spring.hornetq.mode=native
    spring.hornetq.host=localhost
    spring.hornetq.port=5445