In this recipe we are going to look at how you embed an ActiveMQ Broker right into your own applications.
For this recipe we will use the example application named embedded-broker to demonstrate embedded ActiveMQ Brokers. Before proceeding, you should ensure that there are no other broker instances running on your computer.
To run the sample for this recipe, open a terminal, change the path to the directory where embedded-broker is located, and run it by typing mvn compile exec:java
.
In the terminal where you started the example, you will see output similar to the following snippet indicating that the application is running:
Starting the Embedded Broker example now... We sent a Message! Finished running the Embedded Broker example. …
The output of the example in this recipe certainly doesn't look very impressive; what is impressive though is that we didn't have to run a separate broker in order for our example code to work. Because ActiveMQ is a pure Java application, it can easily be embedded into our messaging applications, which can be useful not only in our applications but also for testing application code in continuous integration suites.
In order to embed the broker into our sample application, we first had to add some additional dependencies to our Maven POM file. When embedding brokers, you need to include the following code in your POM file:
<dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-broker</artifactId> <version>5.8.0</version> </dependency> <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-kahadb-store</artifactId> <version>5.8.0</version> </dependency> <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-spring</artifactId> <version>5.8.0</version> </dependency>
These additional libraries bring in everything we need to run a standard broker instance inside our example. Let's look at what each brings to the project:
<activemq-broker>
: As you might have guessed, this is where the core of the ActiveMQ Broker implementation resides. This is required any time you want to embed a broker in your application.<activemq-kahadb-store>
: This library is the home of the default persistence adapter in ActiveMQ. You need to bring this in to use any of the default configurations.<activemq-spring>
: This library brings in the code necessary to create a broker instance from an XML configuration file, be it a pure Spring file or the XBean-based configuration files that ship with ActiveMQ. This could also be omitted if you create the broker using pure Java code; we'll look at that a bit later.
There are of course other dependencies that might need to be brought into your project depending on what broker features you use; these are just the top three. ActiveMQ does provide a single, all-encompassing library named <activemq-all>
that can be included in your Maven POM file. This is useful but does mean your application will acquire a lot of extra dependencies that you will never actually use.
Our sample application consists of the code from our first recipe, Installing ActiveMQ (Simple), modified to create a broker directly in the code. Let's take a look at the code:
public class EmbeddedSimpleJMS { private final String connectionUri = "tcp://localhost:61616"; private ActiveMQConnectionFactory connectionFactory; private Connection connection; private Session session; private Destination destination; private BrokerService service; public void before() throws Exception { service = BrokerFactory.createBroker("xbean:activemq.xml"); service.start(); connectionFactory = new ActiveMQConnectionFactory(connectionUri); connection = connectionFactory.createConnection(); connection.start(); session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); destination = session.createQueue("MyQueue"); } public void after() throws Exception { if (connection != null) { try { connection.close(); } catch (Exception ex) {} } if (service != null) { try { service.stop(); } catch (Exception ex) {} } } public void run() throws Exception { MessageProducer producer = session.createProducer(destination); try { TextMessage message = session.createTextMessage(); message.setText("We sent a Message!"); producer.send(message); } finally { producer.close(); } MessageConsumer consumer = session.createConsumer(destination); try { TextMessage message = (TextMessage) consumer.receive(); } finally { consumer.close(); } } }
In the application's before()
method, we use the class BrokerFactory
to create ActiveMQ's BrokerService
object, which is really an ActiveMQ Broker. The BrokerFactory
class allows us to pass a configuration file that should be used to configure the newly created broker; in our case, we added a very basic ActiveMQ XML configuration file to our Maven project's src/man/resources
directory so that it would automatically be added to the classpath. When the application shuts down, it must stop its BrokerService
object, which we do in the after()
method after we close our connection.
As you can see, it's extremely simple to embed ActiveMQ right inside your application. In ActiveMQ, we make use of this feature to write all of the unit tests for the project; each test creates a broker in its setup code and then shuts it down after the test has run. This is something you can use in your own application tests to ensure your code is using a broker instance with the correct configuration and a known state, without having to use any external tools.
Our simple sample application created a broker using the BrokerFactory
class and a configuration file. If, however, we just want to create a simple BrokerService
instance without the need for a configuration file or dependency on the Spring library, we can create one using pure Java. To do this, we just need to create an instance of BrokerService
and configure it according to our project's needs. The Java code to create a broker equivalent to the one we created in our example would be:
BrokerService broker = new BrokerService(); broker.addConnector("tcp://localhost:61616"); broker.start();
Here, we instantiate a BrokerService
instance and add the connector for the TCP-based transport that our client connects to; everything else we leave at the broker's defaults. We could, if we want to, go one step further and disable persistence so that our sample doesn't need to pull in the <activemq-kahadb-strore>
library in our project POM. The code for that would be:
BrokerService broker = new BrokerService(); broker.addConnector("tcp://localhost:61616"); broker.setPersistent(false); broker.start();
When using embedded ActiveMQ Brokers, people general try to look for a way to restart the broker. There is no restart method or other facility in the BrokerService
class to do a safe restart, so users are often tempted to call stop()
followed by a call to start()
later on, but this won't work. The correct method of restarting a BrokerService
instance is shown in the following code snippet:
broker.stop(); broker.waitUnitStopped(); broker = new BrokerService(); broker.addConnector("tcp://localhost:61616"); broker.start();
More information on the options available when using an embedded broker can be found on the ActiveMQ website, http://activemq.apache.org/how-do-i-embed-a-broker-inside-a-connection.html.