A message broker hosts the destinations (topics and queues), manages delivery, applies options such as transactional delivery and persistent messages, and so on. When configuring the server, you don't create specific destinations, but you can customize things like where persistent messages should be stored and whether the message broker should be clustered.
Since Geronimo starts an ActiveMQ message broker by default, the procedures described in the section are usually not necessary, but they are described in case more extensive ActiveMQ customization is required.
A typical configuration is to deploy a server-wide message broker, and then attach various application-scoped resources to it. Geronimo ships with a basic server-wide message broker configuration called geronimo/activemq-broker/1.0/car. It is started when Geronimo is started in the default configuration, but if it gets disabled for any reason, you can manually start it using a command like this (while the server is running):
java -jar bin/deployer.jar start geronimo/activemq-broker/1.0/car
This configuration includes a TCP transport on port 61616 and a direct transport for clients in the same JVM.
For a more detailed ActiveMQ configuration, you'll use XML snippets to configure the GBeans for the message broker. Depending on how you choose to deploy the broker, you may create a deployment plan to hold these, or you may insert them into the deployment plan for an existing application or module.
GBean configuration and deployment is covered in greater detail in Chapter 18, GBeans: Adding New Services to Geronimo [EMPTY]. The current section gives you enough to deploy a custom message broker, but does not cover the full syntax or options for arbitrary Geronimo services.
A sample GBean configuration looks like this:
Example 7.2. JMS Message Broker Configuration
<import> <groupId>geronimo</groupId> <type>car</type> <artifactId>system-database</artifactId> <version>1.0</version> </import> <dependency> <groupId>activemq</groupId> <artifactId>activemq-core</artifactId> <version>3.2.1</version> </dependency> <dependency> <groupId>activemq</groupId> <artifactId>activemq-gbean</artifactId> <version>3.2.1</version> </dependency> <dependency> <groupId>activeio</groupId> <artifactId>activeio</artifactId> <version>2.0-r118</version> </dependency> <!-- One ActiveMQ Manager should be present in the server at all times. If the default ActiveMQ broker is running then this plan doesn't need one, but if this is the only ActiveMQ broker then it should list the manager GBean. --> <gbean name="ActiveMQ" class="org.activemq.gbean.management.ActiveMQManagerGBean"/> <!-- Message Broker GBeans --> <gbean name="ActiveMQ" class="org.activemq.gbean.ActiveMQContainerGBean"> <attribute name="brokerName"> possibly-unique-broker </attribute> <reference name="persistenceAdapter"> <gbean-name> geronimo.server:j2eeType=JMSPersistence,name=ActiveMQ.cache,* </gbean-name> </reference> </gbean> <gbean name="ActiveMQ.cache" class= "org.activemq.store.cache.SimpleCachePersistenceAdapterGBean"> <attribute name="cacheSize">10000</attribute> <reference name="longTermPersistence"> <gbean-name> geronimo.server:j2eeType=JMSPersistence,name=ActiveMQ.journal,* </gbean-name> </reference> </gbean> <gbean name="ActiveMQ.journal" class= "org.activemq.store.journal.JournalPersistenceAdapterGBean"> <reference name="serverInfo"> <module>geronimo/j2ee-system/1.0/car</module> <type>GBean</type> <name>ServerInfo</name> </reference> <attribute name="directory">var/activemq/journal</attribute> <attribute name="journalType">default</attribute> <reference name="longTermPersistence"> <gbean-name> geronimo.server:j2eeType=JMSPersistence,name=ActiveMQ.jdbc,* </gbean-name> </reference> </gbean> <gbean name="ActiveMQ.jdbc" class="org.activemq.store.jdbc.JDBCPersistenceAdapterGBean"> <reference name="dataSource"> <gbean-name> geronimo.server:J2EEApplication=null,J2EEServer=geronimo, JCAResource=geronimo/system-database/1.0/car, j2eeType=JCAManagedConnectionFactory,name=SystemDatasource </gbean-name> </reference> </gbean> <gbean name="ActiveMQ.tcp.localhost.61616" class="org.activemq.gbean.ActiveMQConnectorGBean"> <attribute name="url">tcp://localhost:61616</attribute> <reference name="activeMQContainer"> <gbean-name> geronimo.server:j2eeType=JMSServer,name=ActiveMQ,* </gbean-name> </reference> </gbean> <gbean name="ActiveMQ.vm.localhost" class="org.activemq.gbean.ActiveMQConnectorGBean"> <attribute name="url">vm://localhost</attribute> <reference name="activeMQContainer"> <gbean-name> geronimo.server:j2eeType=JMSServer,name=ActiveMQ,* </gbean-name> </reference> </gbean>
This is basically split into two parts, a list of dependencies, and a set of GBeans.
The example above uses the same names as the actual ActiveMQ broker configured in Geronimo. Make sure to change all the GBean names and references if you want to deploy another broker in addition to the default geronimo/activemq-broker/1.0/car configuration (instead of replacing it).
The elements in Example 7.2, “JMS Message Broker Configuration” related to dependencies include:
Indicates that another Geronimo configuration should be a parent of this one. In this case, the ActiveMQ broker uses the system database as a parent, because the JDBC persistent store will use the system database.
Holds a single JAR that includes code for the GBeans, or third-party libraries that the GBeans require. Multiple JARs can be listed by using multiple dependency elements.
The URI identifying the dependency, in the standard repository format. The JAR must be located under the repository/ directory of the Geronimo installation.
In this case, a number of JARs are listed, including ActiveMQ itself and a number of dependencies. Make sure the version numbers you list here match the JARs actually present in the geronimo/repository subdirectories.
The rest of the elements in Example 7.2, “JMS Message Broker Configuration” control the GBeans for the JMS Server. There are two JMS GBean types -- the core JMS Server configuration (or ActiveMQContainer) and one or more transports (or ActiveMQConnectors) providing a pathway for JMS resources to communicate with the core JMS Server. Each of the GBean definitions has the same overall form, with elements and attributes including:
The overall wrapper for a single GBean configuration
The unique name to use for this GBean. It is combined with some default settings based on the GBean type and deployment style to create a full GBean Name identifying this component. Note that some of the GBeans here include references to each other, so changing the name of a GBean may require updating the references to it to match. Finally, note that every GBean must have a unique name.
The implementation class for this GBean. There specific values that must be used for this.
Sets a property exposed by the GBean class. When you use an attribute tag, you provide the value as a basic Java type such as String or Integer. The name attribute will be used to identify the setter to invoke on the GBean, the type attribute specifies the data type, and the content of this element is the value to set.
Sets a property exposed by the GBean class. When you use a reference tag, you provide either a gbean-name element with the full GBean Name that identifies another GBean, or a group of child elements that specifically identify certain portions of the GBean name (leaving the rest to use default values).
While that gives you a feel for the structure of the GBean configuration, each of the JMS GBean types requires specific configuration options.
The first GBean in the example creates the core JMS Server. This must be present. The configuration that can be performed here includes:
The name may be changed to something other than ActiveMQ if you like. The connector GBeans need to refer to this one by name, so changes to this will require changed to those.
A name used to identify this ActiveMQ instance.
A pointer to the persistence implementation, which typically involves a back-end data store and a cache on top of it. Normally this GBean refers to the cache, and the cache refers to the underlying persistence mechanism.
The next GBeans in the example create a persistence implementation that is a cache on top of a journaling system on top of a JDBC data store. Some persistence implementation must be present, and while all these layers are not strictly required, they give a good balance between performance and reliability. The ActiveMQContainer GBean must refer to the topmost persistence GBean, and each persistence GBean refers to the next one down the chain. While each persistence GBean is distinct, they are similar and the configuration options are listed together here:
The name may be changed, though the ActiveMQContainer GBean needs to refer to the topmost persistence GBean by name, and each persistence GBean needs to refer to the next by name, so each GBean needs to be kept synchronized with name changes to the GBean it depends upon.
The number of entries the caching GBeans holds in its cache.
This reference should not be changed, as it allows ActiveMQ to discover other elements of the Geronimo configuration. In this case, the journaling GBean uses it to locate a directory to use for its journal.
The directory (relative to the server directory identified by the ServerInfo service) where the journaling GBean stores its journal.
The format used for the journal.
A pointer to the next GBean in the chain, which this one uses to store persistent data.
The database connection pool that the JDBC persistence GBean uses to communicate with the database. This should be a JCAManagedConnectionFactory GBean, where the name is the name of the database pool.
Once the core JMS Server is available, we need to define one or more methods for JMS resources to contact it. This may include network transports, a direct connection for clients in the same JVM, and more. Whichever transports are provided here will be available when we configure JMS resources later. You'll configure one GBean for each transport -- Example 7.2, “JMS Message Broker Configuration” has one GBean for an in-VM transport, and one GBean for a TCP/IP transport.
The recommended transport types are summarized in Table 7.2, “ActiveMQ Transport Types”. Other transport types are available, but they are generally more suitable for peer-to-peer operation instead of a configuration with a JMS Server.
Table 7.2. ActiveMQ Transport Types
The configuration that can be performed on an ActiveMQConnector includes:
A unique name for this GBean.
The URL that clients will use to connect to the JMS Server through this connector. The URL controls how the connector will listen for client connections.
A reference to the core JMS Server. This example uses a gbean-name element, which must exactly match the overall GBean name of the ActiveMQContainer GBean (which includes its gbean:name attribute and some other stuff defined by the implementation class). It's also possible to break up the reference and only list the components that can't be defaulted, using syntax similar to the serverInfo reference above.
The GBeans for the message broker can be deployed in any of the three scopes, though normally they're deployed server-wide.
First, create a deployment plan that's simply a wrapper around the dependencies and GBeans above, and save it to a file such as message-broker-plan.xml (you can use any name). The file should look like this:
<configuration configId="MyJMSBroker" xmlns="http://geronimo.apache.org/xml/ns/deployment-1.0"> <!-- dependency and gbean elements here --> </configuration>
Next, deploy that with a command like this:
java -jar bin/deployer.jar deploy message-broker-plan.xml
(Note that this command assumes that the server is running.)
To deploy a JMS Server to a single application, you'll add the GBean definitions to the deployment plan for the application (which must be packaged as an EAR). This is typically a META-INF/geronimo-application.xml file in the application EAR. If you don't already have a Geronimo deployment plan for the application, you can create one with nothing but the message broker GBean configuration.
A typical geronimo-application.xml deployment plan would look like this:
<application xmlns="http://geronimo.apache.org/xml/ns/j2ee/application-1.0" configId="MyApplication"> <!-- dependency elements here --> ... <!-- gbean elements here --> </application>
Then the application can be packaged and deployed like normal, and the message broker will be started when the application is started.
A client-scoped message broker is configured the same way as an application-scoped message broker, except the GBean configuration is inserted into the deployment plan for a single application module instead of for the application EAR. For example, here's an geronimo-application-client.xml file including a JMS Server as part of an client deployment:
<application-client xmlns= "http://geronimo.apache.org/xml/ns/j2ee/application-client-1.0" configId="MyClientConfig" clientConfigId="MyClient"> <!-- dependency elements here --> ... <!-- gbean elements here --> </openejb-jar>
For the specific ordering of elements within the different module deployment plans, see Chapter 11, Web Applications (WARs) [DRAFT (1.0)], Chapter 12, Enterprise Java Beans (EJB JARs) [DRAFT (1.0)], and Chapter 14, Client Applications (Client JARs) [IN PROGRESS].