Skip to content

AlejandroRivera/embedded-rabbitmq

Repository files navigation

Embedded RabbitMQ

Compatibility: Unix Linux OS X Windows
Builds: Linux CircleCI branch OS X Build Status Windows Build status
Reports: Coverage Status Javadocs
Dist: License Snapshots Maven Central
Social: Gitter chat PayPal donation Flattr donation GratiPay donation

This library allows for the use of various RabbitMQ versions as if it was an embedded service that can be controlled from within the JVM.

The way it works is by downloading, from official repositories, the correct artifact for the given version and operating system, extracting it and starting the RabbitMQ Server with the specified configuration. The broker can then be administered from within the JVM by using equivalent commands to rabbitmqctl or rabbitmq-plugins.

Pre-requisites:

  • This project requires Java 7+
  • RabbitMQ Broker requires Erlang to be installed.

Quick Start:

1. Add a dependency to this project

For Maven:

  <dependency>
      <groupId>io.arivera.oss</groupId>
      <artifactId>embedded-rabbitmq</artifactId>
      <version>X.Y.Z</version>
  </dependency>

For Ivy: <dependency org="io.arivera.oss" name="embedded-rabbitmq" rev="X.Y.Z" />

For Gradle: compile 'io.arivera.oss:embedded-rabbitmq:X.Y.Z'

For SBT: libraryDependencies += "io.arivera.oss" % "embedded-rabbitmq" % "X.Y.Z"

X.Y.Z is the latest released version of this project. For more info visit Maven Central repo or visit the releases page.

For SNAPSHOT releases, add the SonaType repository to your build system: https://oss.sonatype.org/content/repositories/snapshots/

2. Start the RabbitMQ broker

EmbeddedRabbitMqConfig config = new EmbeddedRabbitMqConfig.Builder().build();
EmbeddedRabbitMq rabbitMq = new EmbeddedRabbitMq(config);
rabbitMq.start();

When start() is invoked, the Embedded-RabbitMQ library will download the latest release from RabbitMQ.com that best matches your Operating System. The artifact will be decompressed into a temporary folder, and a new OS process will launch the RabbitMQ broker.

Read more about how to customize your RabbitMQ broker.

3. Verify RabbitMQ is working as you'd expect

ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setVirtualHost("/");
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");

Connection connection = connectionFactory.newConnection();
assertThat(connection.isOpen(), equalTo(true));
Channel channel = connection.createChannel();
assertThat(channel.isOpen(), equalTo(true));

channel.close();
connection.close();

4. Stop the RabbitMQ broker:

rabbitMq.stop();

Customization

Customization is done through the EmbeddedRabbitMqConfig and it's Builder class. All snippets below will refer to this:

EmbeddedRabbitMqConfig.Builder configBuilder = new EmbeddedRabbitMqConfig.Builder();
...
EmbeddedRabbitMqConfig config = configBuilder.build();
EmbeddedRabbitMq rabbitMq = new EmbeddedRabbitMq(config);
rabbitMq.start();

Define a RabbitMQ version to use:

configBuilder.version(PredefinedVersion.LATEST)

or

configBuilder.version(PredefinedVersion.V3_6_5)

By using the version() method, the download URL, executable paths, etc. will be pre-set for Unix/Mac/Windows Operating Systems. You can change the download source from the official rabbitmq.com servers and Github by using the downloadFrom() method:

configBuilder.downloadFrom(OfficialArtifactRepository.GITHUB)

Similarly, if you wish to download another version and/or use another server by specifying a URL:

String url = "https://github.com/rabbitmq/rabbitmq-server/releases/download/rabbitmq_v3_6_6_milestone1/rabbitmq-server-mac-standalone-3.6.5.901.tar.xz";
configBuilder.downloadFrom(new URL(url), "rabbitmq_server-3.6.5.901")

or if you are okay with the existing artifact repositories but you just need a released version not listed in the PredefinedVersion enum:

configBuilder.version(new BaseVersion("3.8.1"))

Downloaded files:

By default, EmbeddedRabbitMq will attempt to save downloaded files to ~/.embeddedrabbitmq. You can change this by making use of the downloadTarget() setter, which accepts both a directory or a file:

configBuilder.downloadTarget(new File("/tmp/rabbitmq.tar.xz"))
...
// configBuilder.downloadTarget(new File("/tmp"))

Warning: If a file with the same name already exists, it will be overwritten.

The default behavior of this library is to re-use previously downloaded files. If you don't wish to use that behavior, disable it:

configBuilder.useCachedDownload(false)

To ensure a corrupted or partially downloaded file isn't re-used, the default behavior is to delete it when the issue is detected. This means that a fresh copy is downloaded next time. To disable this behavior do:

configBuilder.deleteDownloadedFileOnErrors(false)

Extraction path:

EmbeddedRabbitMq will decompress the downloaded file to a temporary folder. You can specify your own folder like so:

configBuilder.extractionFolder(new File("/rabbits/"))

Warning: The content of this folder will be overwritten every time by the newly extracted files/folders.

Advanced RabbitMQ management

If you wish to control your RabbitMQ broker further, you can execute any of the commands available to you in the /bin directory, like so:

RabbitMqCommand command = new RabbitMqCommand(config, "command", "arg1", "arg2", ...);
StartedProcess process = command.call();
ProcessResult result = process.getFuture().get();
boolean success = result.getExitValue() == 0;
if (success) {
  doSomething(result.getOutput());
}

where:

  • command is something like "rabbitmq-ctl" (no need for .bat extension in Windows since it will be automatically appended).
  • args is a variable-length array list, where each element is a word (eg. "-n", "nodeName", "list_users")

See the JavaDocs for more information on RabbitMqCommand and other helper classes like RabbitMqDiagnostics, RabbitMqCtl, RabbitMqPlugins and RabbitMqServer which aim at making it easier to execute common commands.

Enabling RabbitMQ Plugins:

To enable a plugin like rabbitmq_management, you can use the RabbitMqPlugins class like so:

    RabbitMqPlugins rabbitMqPlugins = new RabbitMqPlugins(config);
    rabbitMqPlugins.enable("rabbitmq_management");

This call will block until the command is completed.

You can verify by executing the list() method:

    Map<String, Plugin> plugins = rabbitMqPlugins.list();
    Plugin plugin = plugins.get("rabbitmq_management");
    assertThat(plugin, is(notNullValue()));
    assertThat(plugin.getState(), hasItem(Plugin.State.ENABLED_EXPLICITLY));
    assertThat(plugin.getState(), hasItem(Plugin.State.RUNNING));

You can also see which other plugins where enabled implicitly, by calling the groupedList():

    Map<Plugin.State, Set<Plugin>> groupedPlugins = rabbitMqPlugins.groupedList();
    Set<Plugin> plugins = groupedPlugins.get(Plugin.State.ENABLED_IMPLICITLY);
    assertThat(plugins.size(), is(not(equalTo(0))));

FAQ:

Troubleshooting:

Q: RabbitMQ fails to start due to ERROR: node with name "rabbit" already running on "localhost". Why is this and what can I do?

A: This happens when RabbitMQ fails to be stopped correctly in a previous run. To resolve this issue, manually identify the process and terminate it. To avoid this from happening again, ensure the stop() method is invoked in your code.

Q: RabbitMQ fails to start with a message erl command not found. What's this about?

A: RabbitMQ requires an installation of Erlang to be present in the system. Please install it first.

Q: RabbitMQ fails to start with a message {"init terminating in do_boot",{undef,[{rabbit_prelaunch,start,[]},{init,start_it,1},{init,start_em,1}]}}

A: Most likely you don't have an updated version of Erlang installed.

To check the version of Erlang in your system execute:

$ erl -eval 'erlang:display(erlang:system_info(otp_release)), halt().'  -noshell

RabbitMQ requires:

  • RabbitMQ v3.5.X requires Erlang R13B03 at a minimum.
  • RabbitMQ v3.6.X requires Erlang R16B03 at a minimum (or 17 if you're using SSL/TLS).

For example, if your version is R14B04, you can run RabbitMQ v3.5.X but not 3.6.X.

Read more here: http://www.rabbitmq.com/which-erlang.html

Acknowledgements

This project was inspired from other excellent Open Source libraries, particularly Embedded-MongoDB and Embedded-Redis.

Big thanks to the following OSS projects that made this project possible:

And of course, the biggest thanks to Pivotal and the RabbitMQ team for their hard work.

License

This project is released under Apache License Version 2.0, which basically means:

You can do what you like with the software, as long as you include the required notices. This permissive license contains a patent license from the contributors of the code.

Summary courtesy of: https://tldrlegal.com/license/apache-license-2.0-(apache-2.0)

Say thanks

If you want to say thanks, you can:

  • Star this project
  • Donate:
  • Contribute improvements