Troubleshooting RabbitMQ ACCESS_REFUSED Error

When working with RabbitMQ, you may encounter the following exception:

Exception: org.springframework.amqp.AmqpAuthenticationException: com.rabbitmq.client.AuthenticationFailureException: ACCESS_REFUSED - Login was refused using authentication mechanism PLAIN. For details see the broker logfile.

Configuration Overview

This guide is based on RabbitMQ version 3.3.5 running on Windows. The issue often arises due to incorrect user permissions or configuration settings.

Configuration Steps

To resolve this issue, ensure that your RabbitMQ configuration file located at %APPDATA%\RabbitMQ\rabbit.config includes the following line:

[{rabbit, [{loopback_users, []}]}].

This configuration allows users to connect from remote hosts, which is essential if you are not connecting from localhost.

User Creation

If you have created a user with credentials (e.g., username: test, password: test), ensure that this user has the necessary permissions. You can create a user and set permissions using the RabbitMQ command line tools:

rabbitmqctl add_user test test
rabbitmqctl set_user_tags test administrator
rabbitmqctl set_permissions -p / test ".*" ".*" ".*"

Spring AMQP Configuration

In your Spring application, ensure that your RabbitMQ connection factory is correctly set up. Below is an example configuration snippet:

<!-- RabbitMQ Configuration Start -->
<!-- Connection Factory -->
<rabbit:connection-factory id="rabbitConnFactory" virtual-host="/" username="test" password="test" port="5672"/>

<!-- Spring AMQP Template -->
<rabbit:template id="rabbitTemplate" connection-factory="rabbitConnFactory" routing-key="ecl.down.queue" queue="ecl.down.queue" />

<!-- Spring AMQP Admin -->
<rabbit:admin id="admin" connection-factory="rabbitConnFactory"/>

<rabbit:queue id="ecl.down.queue" name="ecl.down.queue" />
<rabbit:direct-exchange name="ecl.down.exchange">
    <rabbit:bindings>
        <rabbit:binding key="ecl.down.key" queue="ecl.down.queue"/>
    </rabbit:bindings>
</rabbit:direct-exchange>

Example Controller and Message Sender

In your controller class, you can autowire the message sender as follows:

@Autowired
RmqMessageSender rmqMessageSender;

// Inside a method
rmqMessageSender.submitToECLDown(orderInSession.getOrderNo());

Your message sender class should look like this:

import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component("messageSender")
public class RmqMessageSender {
    @Autowired
    AmqpTemplate rabbitTemplate;

    public void submitToRMQ(String orderId) {
        try {
            rabbitTemplate.convertAndSend("Hello World");
        } catch (Exception e) {
            LOGGER.error(e.getMessage());
        }
    }
}

Error Logs

If you continue to face issues, check the RabbitMQ logs for detailed error messages. An example log entry might look like:

=ERROR REPORT==== 7-Nov-2014::18:04:37 ===
closing AMQP connection <0.489.0> (10.1.XX.2XX:52298 -> 10.1.XX.2XX:5672):
    {handshake_error,starting,0,
                     {amqp_error,access_refused,
                                 "PLAIN login refused: user 'guest' can only connect via localhost",
                                 'connection.start_ok'}}

Dependencies

Ensure your pom.xml includes the necessary dependencies for Spring AMQP:

<dependency>
    <groupId>org.springframework.amqp</groupId>
    <artifactId>spring-rabbit</artifactId>
    <version>1.3.6.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-amqp</artifactId>
    <version>4.0.4.RELEASE</version>
</dependency>

Conclusion

If you follow these steps and ensure your configuration is correct, you should be able to resolve the ACCESS_REFUSED error. If problems persist, consider checking your RabbitMQ version and user permissions thoroughly.