I need to connect to Artemis node with ssl.
If I use org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory
and put into brokerURL all parameters:
String brokerURL = "tcp://*:61617?sslEnabled=true&keyStorePath=" + keyStorePath + "&keyStorePassword=" + keyStorePassword + "&trustStorePath=" + pathToTrustStore + "&trustStorePassword=" + trustStorePassword;
It works fine, I can send messages. This factory creates javax.jms.Connection
.
I want to work with jakarta.org.apache.activemq.ActiveMQSslConnectionFactory
or another ActiveMQSslConnectionFactory
.
Application started, but doesn't send/receive messages.
In log file all errors are like:
ERROR \[org.springframework.jms.JmsListenerEndpointContainer#0-1\] Could not refresh JMS Connection for destination 'queue.payments.v3.batch.response' - retrying using FixedBackOff{interval=5000, currentAttempts=9, maxAttempts=unlimited}. Cause: Cannot send, channel has already failed: tcp://*\*.\**:61617
and debug messages like:
DEBUG [ActiveMQ Transport: tcp://*/:61617@50959] Async exception with no exception listener: {}
java.io.EOFException: null
at java.base/java.io.DataInputStream.readInt(DataInputStream.java:398)
at org.apache.activemq.openwire.OpenWireFormat.unmarshal(OpenWireFormat.java:280)
at org.apache.activemq.transport.tcp.TcpTransport.readCommand(TcpTransport.java:240)
at org.apache.activemq.transport.tcp.TcpTransport.doRun(TcpTransport.java:232)
at org.apache.activemq.transport.tcp.TcpTransport.run(TcpTransport.java:215)
at java.base/java.lang.Thread.run(Thread.java:833)
Here is my configuration class:
package com.bottomline.cfrm.ps.notification;
import javax.validation.constraints.NotEmpty;
import org.apache.activemq.ActiveMQSslConnectionFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import jakarta.jms.Connection;
import jakarta.jms.ConnectionFactory;
import jakarta.jms.JMSException;
@Configuration
@EnableJms
public class ActiveMQConfiguration {
@NotEmpty(message = "Name may not be empty")
@Value("${spring.activemq.user}")
private String username;
@NotEmpty(message = "Password may not be empty")
@Value("${spring.activemq.password}")
private String password;
@NotEmpty(message = "Broker URL cannot be empty")
@Value("${spring.activemq.broker-url}")
private String brokerURL;
@NotEmpty(message = "Password cannot be empty")
@Value("${spring.activemq.ssl.keyStorePass}")
private String keyStorePass;
@Value("${spring.activemq.ssl.keyStorePath}")
private String keyStorePath;
@Value("${spring.activemq.ssl.trustStorePath}")
private String trustStorePath;
@Bean
public ActiveMQSslConnectionFactory activeMQSslConnectionFactory() {
ActiveMQSslConnectionFactory factory = new ActiveMQSslConnectionFactory(brokerURL);
try {
factory.setTrustStore(trustStorePath);
} catch (Exception e) {
e.printStackTrace();
}
factory.setTrustStorePassword(keyStorePass);
try {
factory.setKeyStore(keyStorePath);
} catch (Exception e) {
e.printStackTrace();
}
factory.setKeyStorePassword(keyStorePass);
factory.setUserName(username);
factory.setPassword(password);
Connection connection;
try {
connection = factory.createConnection();
connection.start();
} catch (JMSException e) {
e.printStackTrace();
}
return factory;
}
@Bean
public JmsListenerContainerFactory<?> jmsListenerContainerFactory(
@Qualifier("activeMQSslConnectionFactory") ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
configurer.configure(factory, connectionFactory);
return factory;
}
}
And pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.intellinx.solutions</groupId>
<artifactId>TestArtemisMQApplication</artifactId>
<version>1.0.3</version>
<name>TestArtemisMQApplication</name>
<description>Send and Read from Artemis queue</description>
<properties>
<maven.compiler.target>17</maven.compiler.target>
<maven.compiler.source>17</maven.compiler.source>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<!-- For Spring RestClient -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-artemis</artifactId>
</dependency> -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<!--
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-artemis-native</artifactId>
<version>2.0.0</version>
</dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-jms-client-all</artifactId>
<version>2.6.3</version>
</dependency>
<dependency>
<groupId>javax.json</groupId>
<artifactId>javax.json-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0.4</version>
</dependency>
</dependencies>
</project>
I removed jmsListenerContainerFactory
, just to test ability to connect and send. Tried to use javax
instead of jakarta
, but I need all Spring Boot features for other parts of application.
The EOFException
you're getting and its associated stack-trace indicate you're attempting to use the OpenWire JMS client (i.e. org.apache.activemq.ActiveMQSslConnectionFactory
) to connect to a port on ActiveMQ Artemis that only supports the Core protocol (i.e. not OpenWire).
I recommend that you switch back to using org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory
and if you want to get a jakarta.jms.Connection
instead of a javax.jms.Connection
then you just need to use the proper dependencies. Right now you're using this:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
You should remove this and use this one (which has been commented-out):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-artemis</artifactId>
</dependency>
This dependency has a dependency on org.apache.activemq:artemis-jakarta-client
which will give you a Jakarta implementation of Connection
.
Also, you need to remove this as it will interfere with the Artemis Jakarta client dependency:
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-jms-client-all</artifactId>
<version>2.6.3</version>
</dependency>