Authentication for @JmsListener using Spring 4.2 annotations and ActiveMQ
Asked Answered
P

2

10

Trying to implement a non-XML JMS listener using Spring 4 and ActiveMQ. My issue is that I keep getting the following error with my client:

Setup of JMS message listener invoker failed for destination 'topic.FromJndiProperties' [...] 
Cause: The JMS connection has failed: Force close due to SecurityException on connect.
Cause: User name [null] or password is invalid.

So the connection to the destination is being made with username and password null. I think I may have not setup the destinationResolver correctly but I am stuck working out how to resolve this. Can anyone help me fix this?

My AppConfig:

@Autowired
private Environment env;

@Autowired
private BeanFactory springContextBeanFactory;  

@Bean
public DefaultJmsListenerContainerFactory myListenerContainerFactory() throws NamingException {

    Properties props = new Properties();
    props.setProperty(Context.INITIAL_CONTEXT_FACTORY, env.getProperty("java.naming.factory.initial"));
    props.setProperty(Context.PROVIDER_URL, env.getProperty("java.naming.provider.url"));
    props.setProperty(Context.SECURITY_PRINCIPAL, env.getProperty("java.naming.security.principal"));
    props.setProperty(Context.SECURITY_CREDENTIALS, env.getProperty("java.naming.security.credentials"));

    Context jndiContext = new InitialContext(props);;
    ConnectionFactory connectionFactory = (ConnectionFactory) jndiContext.lookup("ConnectionFactory");

    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory);
    factory.setDestinationResolver(new BeanFactoryDestinationResolver(springContextBeanFactory));
    factory.setPubSubDomain(true);
    factory.setSessionAcknowledgeMode(Session.AUTO_ACKNOWLEDGE);

    return factory;
}

The listener:

@JmsListener(containerFactory = "myListenerContainerFactory", destination = "topic.FromJndiProperties")
public void receiveMessage(String message) {
    try {
        System.out.println("Received <" + message + ">");
    } catch (Exception e) {
        e.printStackTrace();
    }
}
Parapet answered 25/2, 2016 at 15:23 Comment(0)
S
2

ConnectionFactory, TopicConnectionFactory and QueueConnectionFactory all have two ways of creating a connection (eg ConnectionFactory.createConnection() and ConnectionFactory.createConnection(username, password).

It seems that the @JmsListener annotation always creates a connection without passing the credentials via the zero args methods.

I used spring's UserCredentialsConnectionFactoryAdapter to wrap my ConnectionFactory for use with @JmsListener so that it passes the credentials when creating connections

Sandstorm answered 12/5, 2020 at 22:13 Comment(0)
R
1

If you have not changed any features on the broker end , try the below

props.setProperty(Context.SECURITY_PRINCIPAL,"admin"
props.setProperty(Context.SECURITY_CREDENTIALS, "admin");

also in your jndi.properties you can add the properties userName=admin and password=admin instead

Rafaelarafaelia answered 29/2, 2016 at 21:24 Comment(1)
Hi Sundar. Thanks for the advice. These values are already being set though. I think there is something odd in how the destination/session is being created.Parapet

© 2022 - 2024 — McMap. All rights reserved.