Чего не хватает в моей конфигурации ActiveMQSslConnectionFactory

Мне нужно подключиться к узлу Artemis с помощью SSL. Если я использую org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory и ввожу вbrokerURL все параметры:

String brokerURL = "tcp://*:61617?sslEnabled=true&keyStorePath = " + keyStorePath + "&keyStorePassword = " + keyStorePassword + "&trustStorePath = " + pathToTrustStore + "&trustStorePassword = " + trustStorePassword;

Все работает нормально, могу отправлять сообщения. Эта фабрика создает javax.jms.Connection.

Я хочу работать с jakarta.org.apache.activemq.ActiveMQSslConnectionFactory или с другим ActiveMQSslConnectionFactory.
Приложение запустилось, но не отправляет/не получает сообщения.

В файле журнала все ошибки такие:

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

и отладочные сообщения типа:

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)

Вот мой класс конфигурации:

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;
      }
}

И 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>

Я удалил jmsListenerContainerFactory, просто чтобы проверить возможность подключения и отправки. Пытался использовать javax вместо jakarta, но мне нужны все функции Spring Boot для других частей приложения.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
0
0
70
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Полученный вами EOFException и связанная с ним трассировка стека указывают, что вы пытаетесь использовать JMS-клиент OpenWire (т. е. org.apache.activemq.ActiveMQSslConnectionFactory) для подключения к порту ActiveMQ Artemis, который поддерживает только протокол Core (т. е. не OpenWire).

Я рекомендую вам вернуться к использованию org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory, и если вы хотите получить jakarta.jms.Connection вместо javax.jms.Connection, вам просто нужно использовать правильные зависимости. Прямо сейчас вы используете это:

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

Вам следует удалить это и использовать это (которое было закомментировано):

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-artemis</artifactId>
        </dependency>

Эта зависимость имеет зависимость от org.apache.activemq:artemis-jakarta-client, что даст вам реализацию Connection в Джакарте.

Кроме того, вам необходимо удалить это, поскольку оно будет мешать зависимости клиента Artemis Jakarta:

      <dependency>
        <groupId>org.apache.activemq</groupId>
         <artifactId>artemis-jms-client-all</artifactId>
         <version>2.6.3</version>
      </dependency>

спасибо за помощь. Мне следует использовать org.apache.activemq.artemis.jms.client.ActiveMQConnectionFac‌​tory только потому, что эта фабрика получает URL-адрес типа tcp://*:61617?sslEnabled=true&keyStorePath=... Но она создает javax.jms.Connection, а затем я нельзя использовать DefaultJmsListenerContainerFactory и JmsTemplate. Знаете ли вы другие зависимости или методы maven для подключения Listener к соединению? Без SSL все работает нормально. И я не могу найти способ добавить SSL.

Matusevich Elena 28.05.2024 10:21

Если вы используете правильные зависимости, как указано в моем ответе, вы получите jakarta.jms.Connection, а не javax.jms.Connection.

Justin Bertram 28.05.2024 16:27

Итак, решение

  1. Используйте org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory из Spring-boot-starter-artemis.

  2. Добавить зависимость

    org.apache.activemq Артемида-Джакарта-сервер
  3. ДляbrokerURL используйте "" , а не "//" в путях к сертификатам.

Другие вопросы по теме