1
votes

I am trying to connect to an ActiveMQ broker running on my local machine using Spring Boot as followed from the this link

In the link, an in-memory broker is used but I am more keen on using a broker server, which in my case I am using ActiveMQ

I am specifying the activemq broker to Spring through the following configurations in the file application.properties present in the class path

spring.activemq.broker-url=stomp://localhost:61611
spring.activemq.password=password
spring.activemq.user=admin

Below are the dependencies from my pom.xml

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.2.RELEASE</version>
</parent>

<properties>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-activemq</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-broker</artifactId>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.activemq/activemq-stomp -->
    <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-stomp</artifactId>
    </dependency>

</dependencies>

Below is the log for ActiveMQ after I have started the server on my local machine

INFO | Refreshing org.apache.activemq.xbean.XBeanBrokerFactory$1@5419f379: startup date [Sun May 07 07:17:36 IST 2017]; root of context hierarchy
INFO | Using Persistence Adapter: KahaDBPersistenceAdapter[F:\Softwares\Browser\apache-activemq-5.14.5-bin\apache-activemq-5.14.5\bin\..\data\kahadb]
INFO | KahaDB is version 6
INFO | Recovering from the journal @1:2260893
INFO | Recovery replayed 3154 operations from the journal in 0.309 seconds.
INFO | PListStore:[F:\Softwares\Browser\apache-activemq-5.14.5-bin\apache-activemq-5.14.5\bin\..\data\localhost\tmp_storage] started
INFO | Apache ActiveMQ 5.14.5 (localhost, ID:FOOTBALL_FIELD-63581-1494121658754-0:1) is starting
INFO | Listening for connections at: tcp://0.0.0.0:61610?maximumConnections=1000&wireFormat.maxFrameSize=104857600
INFO | Connector openwire started
INFO | Listening for connections at: amqp://0.0.0.0:5670?maximumConnections=1000&wireFormat.maxFrameSize=104857600
INFO | Connector amqp started
INFO | Listening for connections at: stomp://0.0.0.0:61611?maximumConnections=1000&wireFormat.maxFrameSize=104857600
INFO | Connector stomp started
INFO | Listening for connections at: mqtt://0.0.0.0:1880?maximumConnections=1000&wireFormat.maxFrameSize=104857600
INFO | Connector mqtt started
WARN | ServletContext@o.e.j.s.ServletContextHandler@338c99c8{/,null,STARTING} has uncovered http methods for path: /
INFO | Listening for connections at ws://127.0.0.1:61612?maximumConnections=1000&wireFormat.maxFrameSize=104857600
INFO | Connector ws started
INFO | Apache ActiveMQ 5.14.5 (localhost, ID:FOOTBALL_FIELD-63581-1494121658754-0:1) started

Application.java

@SpringBootApplication
@EnableJms
public class Application {

@Bean
public JmsListenerContainerFactory<?> myFactory(ConnectionFactory connectionFactory,
                                                DefaultJmsListenerContainerFactoryConfigurer configurer) {
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    // This provides all boot's default to this factory, including the message converter
    configurer.configure(factory, connectionFactory);
    // You could still override some of Boot's default if necessary.
    return factory;
}

@Bean // Serialize message content to json using TextMessage
public MessageConverter jacksonJmsMessageConverter() {
    MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
    converter.setTargetType(MessageType.TEXT);
    converter.setTypeIdPropertyName("_type");
    return converter;
}

public static void main(String[] args) {
    // Launch the application
    ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);

    JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);

    // Send a message with a POJO - the template reuse the message converter
    System.out.println("Sending an email message.");
    jmsTemplate.convertAndSend("mailbox", new Email("info@example.com", "Hello"));
}

}

Requesting DTO Class Email

public class Email {

private String to;
private String body;

//getter setters for fields
//constructors 

@Override
public String toString() {
    return String.format("Email{to=%s, body=%s}", getTo(), getBody());
}

}

Reponse DTO Class ** **

@Component
public class Receiver {

@JmsListener(destination = "mailbox", containerFactory = "myFactory")
public void receiveMessage(Email email) {
    System.out.println("Received <" + email + ">");
}

}

Now when I execute the Spring Boot application, I am getting an error , the stacktrace of which is below

    Exception in thread "main" org.springframework.jms.UncategorizedJmsException: Uncategorized exception occurred during JMS processing; nested exception is javax.jms.JMSException: Could not create Transport. Reason: java.lang.IllegalArgumentException: Invalid connect parameters: {wireFormat.host=localhost}
    at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:316)
    at org.springframework.jms.support.JmsAccessor.convertJmsAccessException(JmsAccessor.java:169)
    at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:487)
    at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:570)
    at org.springframework.jms.core.JmsTemplate.convertAndSend(JmsTemplate.java:658)
    at hello.Application.main(Application.java:49)
Caused by: javax.jms.JMSException: Could not create Transport. Reason: java.lang.IllegalArgumentException: Invalid connect parameters: {wireFormat.host=localhost}
    at org.apache.activemq.util.JMSExceptionSupport.create(JMSExceptionSupport.java:36)
    at org.apache.activemq.ActiveMQConnectionFactory.createTransport(ActiveMQConnectionFactory.java:333)
    at org.apache.activemq.ActiveMQConnectionFactory.createActiveMQConnection(ActiveMQConnectionFactory.java:346)
    at org.apache.activemq.ActiveMQConnectionFactory.createActiveMQConnection(ActiveMQConnectionFactory.java:304)
    at org.apache.activemq.ActiveMQConnectionFactory.createConnection(ActiveMQConnectionFactory.java:244)
    at org.springframework.jms.support.JmsAccessor.createConnection(JmsAccessor.java:180)
    at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:474)
    ... 3 more
Caused by: java.lang.IllegalArgumentException: Invalid connect parameters: {wireFormat.host=localhost}
    at org.apache.activemq.transport.TransportFactory.doConnect(TransportFactory.java:126)
    at org.apache.activemq.transport.TransportFactory.connect(TransportFactory.java:65)
    at org.apache.activemq.ActiveMQConnectionFactory.createTransport(ActiveMQConnectionFactory.java:331)

As a result of this, I am unable to connect to the ActiveMQ broker running on my local machine through Spring Boot.

My requirement is to build a JMS Sender and Receiver over STOMP through ActiveMQ broker in Spring Boot Only. But I am unable to connect to the STOMP URL of the instance f ActiveMQ running on my local.

UPDATE : 11.05.2017 :

After a lot of debugging, I managed to find out that at line # 120 of org.apache.activemq.transport.TransportFactory class has this code Transport transport = createTransport(location, wf) is calling the org.apache.activemq.transport.tcp.TcpTransportFactory implementation of org.apache.activemq.transport.TransportFactory instead of org.apache.activemq.transport.stomp.StompTransportFactory or as a matter of fact any of StompTransportFactory implementations available in activemq-stomp.jar being present in classpath. I want to know if any body can tell me how is the appropriate TransportFactory implementation is selected.

I am stuck on this for almost 3 days. Any type of help or suggestion would be appreciated :)

Cheers!

1

1 Answers

2
votes

Is there any reason that you want to use STOMP in Java in place of using the normal ActiveMQ Java client and protocols like VM or TCP ? STOMP is designed for plain text... your exception is due to the fact that you are using the ActiveMQ client to speak STOMP which it cannot do and to do this you need some other libraries for that maybe spring stomp support but it is not exactly what you try to do http://docs.spring.io/spring-integration/reference/html/stomp.html

if you need STOMP you can use this lib and configure the correspondant beans https://github.com/fusesource/stompjms

UPDATE

As i see in this test https://github.com/fusesource/stompjms/blob/master/stompjms-activemq-test/src/test/java/org/fusesource/stomp/activemq/ActiveMQJmsStompTest.java It is easy to integrate this library to any java or spring client since it implements JMS API. You have to define a bean for the ConnectionFactory :

add to your application.properties

jms.broker.url=tcp://localhost:61611

And update your configuration :

@Value("${jms.broker.url}")
public String host;

@Bean
public ConnectionFactory connectionFactory() throws Exception {
   StompJmsConnectionFactory result = new StompJmsConnectionFactory();
   result.setBrokerURI(host);
   return result;
}