Пользователь Spring JMS HornetQ имеет значение null

Я пытаюсь подключиться к удаленному брокеру HornetQ в приложении spring boot / spring jms и настроить @JmsListener.

HornetQ ConnectionFactory загружается из реестра JNDI, на котором размещен экземпляр HornetQ. Все работает нормально, пока защита HornetQ отключена, но когда она включена, я получаю эту ошибку

WARN  o.s.j.l.DefaultMessageListenerContainer : Setup of JMS message listener invoker failed for destination 'jms/MI/Notification/Queue' - trying to recover. Cause: User: null doesn't have permission='CONSUME' on address jms.queue.MI/Notification/Queue

Я запустил сеанс отладки, чтобы выяснить, что возвращаемый экземпляр ConnectionFactory - это HornetQXAConnectionFactory, но поля пользователя и пароля не установлены, что, как я считаю, является причиной того, что user имеет значение null. Я проверил, что основной пользователь и учетные данные установлены в свойствах JNDI, но каким-то образом они не передаются в экземпляр ConnectionFactory. Любая помощь в том, как я могу заставить эту настройку работать, была бы принята с благодарностью.

Это моя конфигурация, связанная с jms

@Configuration
@EnableJms
public class JmsConfig {

    @Bean
    public JmsListenerContainerFactory<?> jmsListenerContainerFactory(ConnectionFactory connectionFactory,
            DefaultJmsListenerContainerFactoryConfigurer configurer) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();

        configurer.configure(factory, connectionFactory);

        factory.setDestinationResolver(destinationResolver());
        return factory;
    }

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

    @Value("${jms.jndi.provider.url}")
    private String jndiProviderURL;
    @Value("${jms.jndi.principal}")
    private String jndiPrincipal;
    @Value("${jms.jndi.credentials}")
    private String jndiCredential;

    @Bean
    public JndiTemplate jndiTemplate() {
        Properties env = new Properties();
        env.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
        env.put("java.naming.provider.url", jndiProviderURL);
        env.put("java.naming.security.principal", jndiPrincipal);
        env.put("java.naming.security.credentials", jndiCredential);
        return new JndiTemplate(env);
    }
    @Bean
    public DestinationResolver destinationResolver() {
        JndiDestinationResolver destinationResolver = new JndiDestinationResolver();
        destinationResolver.setJndiTemplate(jndiTemplate());
        return destinationResolver;
    }

    @Value("${jms.connectionfactory.jndiname}")
    private String connectionFactoryJNDIName;

    @Bean
    public JndiObjectFactoryBean connectionFactoryFactory() {
        JndiObjectFactoryBean jndiObjectFactoryBean = new JndiObjectFactoryBean();
        jndiObjectFactoryBean.setJndiTemplate(jndiTemplate());
        jndiObjectFactoryBean.setJndiName(connectionFactoryJNDIName);
        jndiObjectFactoryBean.setResourceRef(true);
        jndiObjectFactoryBean.setProxyInterface(ConnectionFactory.class);
        return jndiObjectFactoryBean;
    }

    @Bean
    public ConnectionFactory connectionFactory(JndiObjectFactoryBean connectionFactoryFactory) {
        return (ConnectionFactory) connectionFactoryFactory.getObject();
    }
}
Пользовательский скаляр 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 .
1
0
448
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

JNDI и JMS на 100% независимы, поскольку это совершенно разные спецификации, реализованные потенциально совершенно разными способами. Поэтому учетные данные, которые вы используете для поиска JNDI, не применяются к вашим ресурсам JMS. Вам необходимо явно указать имя пользователя и пароль для вашего JMS-соединения. Это легко использовать напрямую через JMS API (например, через javax.jms.ConnectionFactory#createConnection(String username, String password)). Поскольку вы используете Spring, вы можете использовать что-то вроде этого:

@Bean
public ConnectionFactory connectionFactory(JndiObjectFactoryBean connectionFactoryFactory) {
    UserCredentialsConnectionFactoryAdapter cf = new UserCredentialsConnectionFactoryAdapter();
    cf.setTargetConnectionFactory((ConnectionFactory) connectionFactoryFactory.getObject());
    cf.setUsername("yourJmsUsername");
    cf.setPassword("yourJmsPassword");
    return cf;
}

Кроме того, как бы то ни было, кодовая база HornetQ была подарена проекту Apache ActiveMQ сейчас три с половиной года назад и продолжает жить как брокер Apache ActiveMQ Artemis. С тех пор было выпущено 22 релиза с множеством новых функций и исправлений ошибок. Я настоятельно рекомендую вам выполнить миграцию, если это вообще возможно.

Оберните фабрику соединений в UserCredentialsConnectionFactoryAdapter.

Gary Russell 01.01.2019 17:36

@Justin Bertram Я использую spring jms, который сам по себе создает соединение и, кажется, использует javax.jms.ConnectionFactory#createConnection() без аргументов.

mzzzzb 01.01.2019 17:48

Я обновил свой ответ потенциальным решением Spring.

Justin Bertram 01.01.2019 19:59

Оберните фабрику соединений в UserCredentialsConnectionFactoryAdapter.

/**
 * An adapter for a target JMS {@link javax.jms.ConnectionFactory}, applying the
 * given user credentials to every standard {@code createConnection()} call,
 * that is, implicitly invoking {@code createConnection(username, password)}
 * on the target. All other methods simply delegate to the corresponding methods
 * of the target ConnectionFactory.
 * ...

выглядит многообещающе. попробую

mzzzzb 01.01.2019 17:45

работает, спасибо. вы сначала указали на решение, но я принимаю ответ @ justin_bertram, поскольку он имеет более подробный ответ

mzzzzb 02.01.2019 06:22

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