Hot questions for Using RabbitMQ in qpid

Question:

I wanted to set up a little local test for some components connecting to RabbitMQ. For this, one solution seems to be the QPID In-Memory Broker and actually that works quite well when following these instructions (only using the current version of 7.0.3 instead of 7.0.0)...

For Rabbit MQ, I removed the "AMQP_1_0" protocol and only added the qpid-broker-plugins-amqp-0-8-protocol dependency. Also I replaced the Authenticationprovider with a PLAIN. This was enough to get my RabbitMQ components working and sending/receiving messages through that Broker.

But the problem is this line...

"port" : "${qpid.amqp_port}",

As far as I understand it, this should allow me to define the port the broker is listening at by setting this property when calling systemLauncher.startup.

attributes.put("qpid.amqp_port", 12345);

Unfortunately, this does not work and the Broker always listens at the default port (5672, iirc). Obviously this is not optimal for automated tests, so I am looking for one of the following possibilities (or a better one):

  1. Putting a random port in the properties (I can find an open port myself, no problem) or...
  2. Telling QPID to use a random (open) port - but then I also need to know which port is actually used, since SystemLauncher does not seem to offer any way to query that.

Answer:

Apache Qpid Broker-J's SystemLauncher supports SystemLauncherListeners which get notified once a various points through the startup sequence. If you configure the Broker to bind to port 0, a dynamically assigned port will be assigned at run-time. You can then use an #afterStartup() implementation to determine which port has been bound. Take a look at PortExtractingLauncherListener (test harness code) as an example to follow.

In Broker-J's model there is a distinction between an object's attributes and context variables. If you want to provide a substitution for qpid.amqp_port you do this by providing a context variable. You can so this programmatically like so:

attributes.put("context", Collections.singletonMap("qpid.amqp_port", 0))

or, as context variables are defaulted from Java system properties, like this on the JVM command line -Dqpid.amqp_port=0

Question:

I'm trying to write an integration test for an application that uses RabbitMQ and for that I'm using Qpid broker. I managed to start the server and my test is connecting to it, but I need to create the queues in Qpid before startup. Because I have a large number of queues, I create the beans dynamically:

applicationContext.getBeanFactory().registerSingleton(queueName, queue);

And this requires the queues to be created before startup.

This is the qpid config file:

{
  "name": "tst",
  "modelVersion": "2.0",
  "defaultVirtualHost" : "default",
  "authenticationproviders" : [ {
    "name" : "noPassword",
    "type" : "Anonymous",
    "secureOnlyMechanisms": []
        },
    {
      "name" : "passwordFile",
      "type" : "PlainPasswordFile",
      "path" : "/src/test/resources/passwd.txt",
      "secureOnlyMechanisms": [],
      "preferencesproviders" : [{
        "name": "fileSystemPreferences",
        "type": "FileSystemPreferences",
        "path" : "${qpid.work_dir}${file.separator}user.preferences.json"
        }
      ]
    }
   ],
  "ports" : [
    {
      "name": "AMQP",
      "port": "5673",
      "authenticationProvider": "passwordFile",
      "protocols": [
        "AMQP_0_10",
        "AMQP_0_8",
        "AMQP_0_9",
        "AMQP_0_9_1"
      ]
    }],
  "virtualhostnodes" : [ {
    "name" : "default",
    "type" : "JSON",
    "virtualHostInitialConfiguration" : "{ \"type\" : \"Memory\" }"
  }]

}

An from the official documentation(https://qpid.apache.org/releases/qpid-broker-j-7.1.4/book/Java-Broker-Management-Channel-REST-API.html#d0e2130) I read that the queues can be created to REST calls so I tried to use RestTemplate to achieve that, but it doesn't seem to create the queues.

    @BeforeClass
    public static void startup() throws Exception {
        brokerStarter = new BrokerManager();
        brokerStarter.startBroker();

        RestTemplate restTemplate = new RestTemplate();
        restTemplate.put("http://localhost:5673/api/latest/queue/default/queue1", "");
        restTemplate.put("http://localhost:5673/api/latest/queue/default/queue-2", "");
    }

Can someone explain what am I doing wrong? Thank you!


Answer:

I managed to solve that by using connection factory:

            @Autowired
            ConnectionFactory factory;

            ....
            factory.setHost("localhost");
            factory.setPort(qpid_server_port);
            try (Connection connection = factory.newConnection(); Channel channel = connection.createChannel()) {
                String queue = "queue-x";
                channel.queueDeclare(queue, true, false, false, null);
                //channel.queueBind(queue, "exchange-x" , "routing-key-x");

            } catch (Exception e) {
                e.printStackTrace();
            }