WebLogic Integration

Connectivity > Containers > WebLogic Integration

ActiveMQ Classic WebLogic Integration

ActiveMQ Classic clients and brokers can be run in WebLogic Server or WebLogic Express. This is usually done for licensing reasons:

  • WebLogic Server includes JMS client and server features, but it may cost extra to use these JMS features to connect multiple servers together (as opposed to only using JMS internally within one server)
  • WebLogic Express disables the JMS features via the license, so while JMS classes are on the class path, there are no JMS features available.
    An ActiveMQ Classic broker may be run within WebLogic to provide JMS features while avoiding these issues. As well, an ActiveMQ Classic client may be run within WebLogic to connect to either an ActiveMQ Classic broker running in the same WebLogic instance, and ActiveMQ Classic broker running in a remote WebLogic instance, or a standalone ActiveMQ Classic broker running elsewhere on the network.

ActiveMQ Classic Clients in WebLogic

An ActiveMQ Classic client can be run in any recent version of WebLogic. However, the specifics depend on which revision of JMS is supported by your version of WebLogic.

WebLogic Server/Express versions including JMS 1.0.x

This is known to include WebLogic 8.1 and all previous versions.

Note: ActiveMQ Classic cannot deliver messages to message-driven beans in this version of WebLogic. You will need to create JMS clients manually to send and receive JMS messages.

To work with ActiveMQ Classic from one of these releases of WebLogic, you should not include any javax.jms classes with your application, but should instead use the JMS 1.0.x classes distributed with WebLogic. This means you should not use a fully-aggregated ActiveMQ Classic JAR such as activemq-4.0.1/incubator-activemq-4.0.1.jar but instead, individual ActiveMQ Classic JARs such as activemq-4.0.1/lib/activeio-core-3.0-beta3.jar and activemq-4.0.1/lib/activemq-core-4.0.1.jar.

Further, your code should use only JMS 1.0.x versions of the JMS interfaces (such as javax.jms.Session). Note that JMS 1.1 uses many of the same interfaces, but has added numerous methods to them, and if you use the new methods your code will not run in this version of WebLogic. Try to ensure you’re compiling your client code against the weblogic.jar from the correct version of WebLogic, or else a dedicated JMS 1.0.x JAR such as the one you can download from Sun. Do not compile against a JAR like activemq-4.0.1/incubator-activemq-4.0.1.jar because that JAR includes JMS 1.1!

Finally, you can connect to ActiveMQ Classic using the normal ActiveMQ Classic JNDI settings including a connect URL. Do not attempt to use WebLogic JNDI to connect to ActiveMQ Classic, and do not use the WebLogic host name or listen port in the ActiveMQ Classic connect URL – even if the ActiveMQ Classic broker is run within WebLogic it will listen on a separate network port from the one that WebLogic uses.

TODO: Add sample JMS 1.0.x code

WebLogic Server versions including JMS 1.1

WebLogic 9.2 and above are known to support JMS 1.1. (I don’t know what JMS release WebLogic 9.0-9.1 support)

To work with ActiveMQ Classic in one of these release of WebLogic Server, you can use the J2EE Connector included with ActiveMQ Classic (known as ActiveMQ Classic-RA). This will provide full ActiveMQ Classic support to J2EE applications – ActiveMQ Classic can be used to both send messages and to deliver incoming messages to message-driven beans. Your J2EE applications can map connection factory and destination references in JNDI.

I don’t have an example of using the J2EE Connector from a J2EE 1.4 application in WebLogic. If someone can contribute one that would be great!

If you’re using Spring or another non-J2EE architecture in your application, you may choose to skip the J2EE Connector and just connect directly to ActiveMQ Classic using the technique described in the next section.

WebLogic Express versions including JMS 1.1

WebLogic 9.2 and above are known to support JMS 1.1. (I don’t know what JMS release WebLogic 9.0-9.1 support)

J2EE Connectors are not supported in WebLogic Express, so that approach is out. Instead, any components that want to connect to ActiveMQ Classic need to manually create the connection (or use a technique like Spring message-driven POJOs to manage it). However, this should be relatively trouble-free since ActiveMQ Classic and WebLogic support the same JMS release.

TODO: Example of JMS 1.1 client and Spring Message-Driven POJO client for WebLogic

ActiveMQ Classic Brokers in WebLogic

On the surface it’s not obvious why you might want to run an ActiveMQ Classic broker within WebLogic instead of standalone, but the considerations include:

  • When ActiveMQ Classic is run within WebLogic, it can be deployed, started, stopped, and redeployed like other applications, using the WebLogic console or other tools, while the JVM and WebLogic are still running
  • ActiveMQ Classic can hook into the WebLogic JMX management system (as well as e.g. JRockit) to provide a single management interface to the app server, applications, ActiveMQ Classic, and even the JVM.
  • ActiveMQ Classic can leverage WebLogic security realms for authentication and authorization – not only are there more security realm types available for WebLogic, but they’re also easier to configure via the WebLogic console

If you decide to run ActiveMQ Classic standalone, that’s fine, you can skip this section. Otherwise, read on.

The specific integration techniques depend on whether you’re using WebLogic Server or WebLogic Express, and whether your version supports JMS 1.0.x or JMS 1.1.

WebLogic Server/Express versions including JMS 1.0.x

Deploying an ActiveMQ Classic broker in a release of WebLogic Server or WebLogic Express that supports only JMS 1.0.x has not been tested. This is known to include WebLogic 8.1 and all previous versions. It will probably have trouble due to conflicting versions of JMS used by ActiveMQ Classic and by WebLogic.

Please report your results if you try this

WebLogic Server versions including JMS 1.1

WebLogic 9.2 and above are known to support JMS 1.1. (I don’t know what JMS release WebLogic 9.0-9.1 support)

It is possible to deploy ActiveMQ Classic in WebLogic Server in one of two ways:

  • Using the ActiveMQ Classic-RA J2EE Connector – ActiveMQ Classic provides a J2EE Connector that is normally used by clients to connect to a separate ActiveMQ Classic broker. However, the J2EE Connector accepts arguments to run an embedded broker and provide the location of an XML config file for an embedded broker. This is probably the best way to deploy an ActiveMQ Classic broker in WebLogic Server, because ActiveMQ Classic then has access to WebLogic thread pools and other resources.
  • Deploying an ActiveMQ Classic Broker as a WebLogic Application – This is the technique described below for WebLogic Express. It works equally well in WebLogic Server.

The J2EE Connector approach has not be specifically tested, but should work well. It would need some additional classes to support the security and management integration as described in the next section, so those would need to be added to a JAR which is in turn added to the J2EE Connector RAR file. Please report your results if you try this

WebLogic Express versions including JMS 1.1

WebLogic 9.2 and above are known to support JMS 1.1. (I don’t know what JMS release WebLogic 9.0-9.1 support)

Since WebLogic Express does not support J2EE Connectors, it is necessary to deploy ActiveMQ Classic wrapped in an application that is deployed to WebLogic. Note that ActiveMQ Classic runs in the XBean container, so XBean must be pointed to an appropriate configuration file to start up and it will then configure and start all the ActiveMQ Classic components. The first challenge is then to construct an application that locates the right config file(s) and starts the ActiveMQ Classic broker when it is deployed.

ActiveMQ Classic as a WebLogic Application

The easiest type of WebLogic application to configure with all the needed ActiveMQ Classic libraries and configuration and not much else is a web application. The JARs go in WEB-INF/lib/ and config files typically in WEB-INF/. The only necessary configuration for the web application itself is to install a listener that will start and stop ActiveMQ Classic when the web application is started and stopped. There are also a couple optional classes that can be used to integrate ActiveMQ Classic with WebLogic’s security system. Additionally, in this example, a simple web page included in the WAR will be available whenever ActiveMQ Classic is running, so a simple HTTP request can determine whether the ActiveMQ Classic module has been started.

Management Options

ActiveMQ Classic exposes a number of management and monitoring features via JMX. There are three ways to expose these JMX objects:

  1. Have ActiveMQ Classic start its own JMX MBeanServer and network connector (typically on port 1099)
  2. Have ActiveMQ Classic use the JVM’s MBeanServer (for Java 5 and higher, either Sun VM or JRockit VM)
  3. Have ActiveMQ Classic use the MBeanServer provided by a runtime environment such as WebLogic

Each approach has its advantages and disadvantages. A few things to note:

  • Make sure that each ActiveMQ Classic instance on the same machine uses a separate network port to handle JMX requests. This is set in the config file when using the ActiveMQ Classic MBeanServer, in a system property (command-line argument) when using the JVM’s MBeanServer, and it uses the standard WebLogic listen port for WebLogic JMX
  • JRockit appears to require a runtime license to use the embedded MBeanServer, while the Sun JVM provides it for free

The sample below includes an optional configuration block that lets ActiveMQ Classic hook into the WebLogic runtime MBeanServer. This means ActiveMQ Classic MBeans will appear alongside WebLogic MBeans (and even JVM MBeans if they are enabled). With this approach, management clients will access ActiveMQ Classic MBeans through the normal WebLogic listen port (e.g. 7001) rather than using a dedicated JMX port, though IIOP must be enabled for this to work. However, note that this is optional, and you can skip that configuration block and use one of the other approaches (JVM or embedded MBeanServer) to expose the ActiveMQ Classic MBeans.

Security Options

ActiveMQ Classic has optional authentication and authorization plugins, which are based on JAAS. Fortunately, WebLogic provides a JAAS LoginModule that performs the authentication against the default WebLogic security realm, and returns the appropriate principals for authorization. Unfortunately, by default, ActiveMQ Classic cannot authorize access to specific users within the security realm based on WebLogic principals, meaning either there’s no security or a login is required but any user with a valid login has full access to ActiveMQ Classic. However, with custom security classes like the ones shown below, ActiveMQ Classic can use the WebLogic security realm to process a login and then you can configure the WebLogic principals (users and/or groups) that should be allowed to perform read/write/create/remove actions on a per-broker or per-destination basis.

You may choose to use authentication only, in which case any user with a valid WebLogic login can access ActiveMQ Classic, and no custom code is necessary. You may also add authorization to that using some custom code, to apply specific security constraints to specific users or destinations. For purposes of this example, we have only implemented an authorization approach that allows any member of a single specific WebLogic group to access all resources in ActiveMQ Classic. Between the authorization plugin provided here and the default one provided with ActiveMQ Classic, you should have the foundation to enhance this if more feature-rich authorization is required.

Persistence Options

ActiveMQ Classic uses a combination of a local journal (files on the file system) and a backing database by default. In the standard configuration, an embedded Derby database is used. This runs fine in WebLogic, but it’s also possible to have ActiveMQ Classic use a database connection pool defined in WebLogic, rather than using a separate Derby database. The configuration files shown later have commented-out sections referring to a WebLogic database connection pool – if you want to use those, you’ll just need to set the correct JNDI name that was used for the database connection pool.

Note that ActiveMQ Classic will create the tables it needs the first time it connects to a database, so no particular preparation is required for the database.

ActiveMQ Classic Integration Architecture

The ActiveMQ Classic-in-WebLogic combination looks like this:

To summarize this diagram:

  • ActiveMQ Classic runs as a web application, which runs in the web container inside WebLogic Express
  • ActiveMQ Classic reads two configuration files from a directory on the WebLogic class path – one to configure ActiveMQ Classic itself, and one to configure its logging output
  • ActiveMQ Classic uses two main resources from WebLogic Express – the JMX management server (MBeanServer) and the WebLogic security realm (in the form of a JAAS LoginModule).
  • In order to start ActiveMQ Classic when the web application is deployed, the web.xml includes a context listener for Spring, and the Spring applicationContext.xml file loads the ActiveMQ Classic broker and points it to the ActiveMQ Classic configuration file (which as mentioned above, is stored in a directory on the class path).
  • Within ActiveMQ Classic:
    • A configuration block in the ActiveMQ Classic configuration file causes ActiveMQ Classic to register all its JMX MBeans with the WebLogic JMX MBeanServer
    • A security plugin causes all clients to authenticate against the WebLogic security realm
    • The security plugin also reads the name of a WebLogic group from the ActiveMQ Classic configuration file, and requires that any client must be a member of that group (when WebLogic processed the login, it must have created a principal for that group for the user)
    • The ActiveMQ Classic configuration file also identifies a network listen port that ActiveMQ Classic will listen on for JMS clients. Any clients must include the server’s hostname and this listen port in their connect URL.
    • The ActiveMQ Classic logging system (Log4J) outputs log message in the format specified in and to the destinations specified in the logging configuration file
    • Persistent messages are stored to the journal in the ActiveMQ Classic Data Directory and periodically spooled to a remote database (database not shown in diagram)
  • Note that ActiveMQ Classic uses its own threads; since WebLogic Express does not support J2EE Connectors, it is not possible for ActiveMQ Classic to access a WebLogic thread pool without more extensive customization

Building the ActiveMQ Classic to WebLogic Integration WAR

This section discusses the code, libraries, and configuration files necessary to build the ActiveMQ Classic web application that will be deployed in WebLogic Express.

Starting and Stopping ActiveMQ Classic

ActiveMQ Classic needs to start when the web application is deployed or started, and stop when the web application is stopped or undeployed. The easiest way to do this is to a use the commonly available Spring listeners, which start a Spring context, which can point ActiveMQ Classic to an XBean configuration file, which starts ActiveMQ Classic. A little roundabout, but it works well in practice with very little configuration.

J2EE WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app\_2\_4.xsd" >
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

Spring WEB-INF/applicationContext.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <bean id="brokerService" class="org.apache.activemq.xbean.BrokerFactoryBean">
        <property name="config" value="classpath:activemq-config.xml"/>
    </bean>
</beans>

Again, the web.xml listener starts Spring and reads the Spring META-INF/applicationContext.xml file (the default location used by the ContextLoaderListener), and the applicationContext.xml indicates that the ActiveMQ Classic configuration file should be read from the class path with the name activemq-config.xml. That file could be placed in WEB-INF/classes or in a directory on the file system that is added to the WebLogic class path (for ease of editing).

With this approach, the normal WebLogic deployment tools, admin console, etc. can be used to deploy, start, stop, and restart ActiveMQ Classic (packaged into a web application WAR).

Required Libraries

ActiveMQ Classic required a number of JARs which should be included in the web application WEB-INF/lib directory.

This list was generated for ActiveMQ Classic 4.0.1:

  • activemq-core (basic ActiveMQ Classic code)
  • activemq-jaas (ActiveMQ Classic security code)
  • activeio-core (ActiveMQ Classic networking layer)
  • derby (embedded DB for persistent messages)
  • commons-logging (logging abstraction library)
  • log4j (actual logging package used)
  • backport-util-concurrent (concurrency utility library)
  • spring (used to configure and start ActiveMQ Classic)
  • xbean-spring (used to configure ActiveMQ Classic)

Additionally, to build the custom security plugins, the WebLogic server/lib/weblogic.jar is presently required at compile time.

Of these, Derby could be omitted if ActiveMQ Classic was configured to not use a database for persistence or to use a separate database (e.g. a WebLogic database pool) for persistence. The WebLogic JAR is needed only at build time (it’s provided by the server at runtime). Spring could be omitted if a different strategy was used to start and stop ActiveMQ Classic when the web app was started or stopped (a little custom code could replace this dependency). The rest are probably unavoidable, unless ActiveMQ Classic changes its dependencies in a future version.

WebLogic Integration Code

There are two custom classes used for this example. We’ll show in a minute how to configure ActiveMQ Classic to use these. Note that these are optional – if you don’t want to leverage WebLogic’s security realm, you can skip these.

The first class makes ActiveMQ Classic use the WebLogic security realm for authentication, and lets you specify a single WebLogic group to use for authorization (only members of that group can access ActiveMQ Classic, though group members have full access to ActiveMQ Classic).

ActiveMQToWebLogicSecurity.java

This class is an ActiveMQ Classic “plugin”, which installs two filters (authorization and authentication) which will be invoked on every request. This is similar to the default behavior provided by ActiveMQ Classic’s JaasAuthenticationPlugin and AuthorizationPlugin.

/**
 * An ActiveMQ Classic security plugin that installs two security filters
 * (authentication and authorization) that use WebLogic security realms to
 * handle the login and provide user and group principals.
 */
public class ActiveMQToWebLogicSecurity implements BrokerPlugin {
    private String authorizedGroup;

    public Broker installPlugin(Broker broker) {
        // Install the first filter for authentication
        Broker first = new ActiveMQWebLogicAuthenticationFilter(broker);
        // Configure and install the second filter for authorization
        AuthorizationEntry entry = new AuthorizationEntry();
        Set acls = new HashSet();
        acls.add(new WLSGroupImpl(authorizedGroup));
        entry.setAdminACLs(acls);
        entry.setReadACLs(acls);
        entry.setWriteACLs(acls);
        DefaultAuthorizationMap map = new DefaultAuthorizationMap();
        map.setDefaultEntry(entry);
        //todo: if finer-grained access is required, add more entries to the authorization map
        Broker second = new AuthorizationBroker(first, map);
        return second;
    }

    public String getAuthorizedGroup() {
        return authorizedGroup;
    }

    /**
     * Called by XBean at configuration time to set the authorized group from a
     * property in the main ActiveMQ Classic configuration file.
     */
    public void setAuthorizedGroup(String authorizedGroup) {
        this.authorizedGroup = authorizedGroup;
    }
}

The second class is the authentication filter used by the class above to authenticate all logins against the WebLogic default security realm.

ActiveMQWebLogicAuthenticationFilter.java

/**
 * A broker filter that authenticates callers against WebLogic security.
 * This is similar to the ActiveMQ Classic JaasAuthenticationBroker except for two
 * things:
 * <ul>
 *   <li>Instead of reading a JAAS configuration file, it hardcodes the JAAS
 *     configuration to require authentication against WebLogic</li>
 *
 *   <li>The SecurityContext implementation overrides the method used to
 *     compare actual and eligible principals in order to handle the fact
 *     that WebLogic principals (WLSGroupImpl in particular) do not seem
 *     to match according to equals and hashCode even if the principal class
 *     and principal name are the same (perhaps having to do with the
 *     signature data on the WLSAbstractPrincipal).</li>
 * </ul>
 */
public class ActiveMQWebLogicAuthenticationFilter extends BrokerFilter {
    private final static Configuration WEBLOGIC\_JAAS\_CONFIGURATION = new Configuration() {
        public AppConfigurationEntry\[\] getAppConfigurationEntry(String name) {
            return new AppConfigurationEntry\[\]{
                    new AppConfigurationEntry("weblogic.security.auth.login.UsernamePasswordLoginModule",
                            AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, Collections.EMPTY_MAP)
            };
        }

        public void refresh() {
        }
    };
    private final CopyOnWriteArrayList securityContexts = new CopyOnWriteArrayList();

    public ActiveMQWebLogicAuthenticationFilter(Broker next) {
        super(next);
    }

    static class JaasSecurityContext extends SecurityContext {

        private final Subject subject;

        public JaasSecurityContext(String userName, Subject subject) {
            super(userName);
            this.subject = subject;
        }

        public Set getPrincipals() {
            return subject.getPrincipals();
        }

        /**
         * This is necessary because WebLogic uses extra logic when comparing principals,
         * probably to check whether they are cryptographically signed (which WebLogic
         * supports).  We skip that test because ActiveMQ Classic does not sign the principals
         * it deals with.
         */
        public boolean isInOneOf(Set eligiblePrincipals) {
            for (Iterator it = getPrincipals().iterator(); it.hasNext();) {
                Principal test = (Principal) it.next();
                for (Iterator el = eligiblePrincipals.iterator(); el.hasNext();) {
                    Principal eligible = (Principal) el.next();
                    if(test.getName().equals(eligible.getName()) &&
                            test.getClass().getName().equals(eligible.getClass().getName())) {
                        return true;
                    }
                }
            }
            return false;
        }
    }

    public void addConnection(ConnectionContext context, ConnectionInfo info) throws Exception {
        if( context.getSecurityContext()==null ) {
            // Do the login.
            try {
                LoginContext lc = new LoginContext("ActiveMQ", new Subject(),
                        new URLCallbackHandler(info.getUserName(), info.getPassword()),
                        WEBLOGIC\_JAAS\_CONFIGURATION);
                lc.login();
                Subject subject = lc.getSubject();

                SecurityContext s = new JaasSecurityContext(info.getUserName(), subject);
                context.setSecurityContext(s);
                securityContexts.add(s);
            } catch (Exception e) {
                throw (SecurityException)new SecurityException("User name or password is invalid.").initCause(e);
            }
        }
        super.addConnection(context, info);
    }

    public void removeConnection(ConnectionContext context, ConnectionInfo info, Throwable error) throws Exception {
        super.removeConnection(context, info, error);
        if( securityContexts.remove(context.getSecurityContext()) ) {
            context.setSecurityContext(null);
        }
    }

    /**
     * Previously logged in users may no longer have the same access anymore.  Refresh
     * all the logged into users.
     */
    public void refresh() {
        for (Iterator iter = securityContexts.iterator(); iter.hasNext();) {
            SecurityContext sc = (SecurityContext) iter.next();
            sc.getAuthorizedReadDests().clear();
            sc.getAuthorizedWriteDests().clear();
        }
    }
}
Sample ActiveMQ Classic Configuration Files

This section shows three sample ActiveMQ Classic configuration files – one for a single broker with the security and management plugins listed above, and one for a network of two brokers with the security and management plugins listed above. If you want to skip the security and management plugins, you can remove those attributes from the main <broker> element and remove the <bean> definitions for them below.

It also shows a Log4J configuration file, which controls the ActiveMQ Classic log output.

Single Broker

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://activemq.org/config/1.0">
  <!-- Allows us to use system properties as variables in this configuration file -->
  <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
  
  <broker useJmx="true" brokerName="MyBroker" useShutdownHook="false"
          plugins="#WebLogicSecurity">

    <!-- Register all ActiveMQ Classic MBeans with the WebLogic runtime MBeanServer -->
    <managementContext>
      <managementContext>
          <MBeanServer>
             <bean class="org.springframework.jndi.JndiObjectFactoryBean" xmlns="">
                <property name="jndiName" value="java:comp/env/jmx/runtime" />
                <property name="lookupOnStartup" value="true" />
                <property name="expectedType" value="javax.management.MBeanServer" />
             </bean>
          </MBeanServer>
      </managementContext>
    </managementContext>
  
    <persistenceAdapter>
      <!-- By default, use an embedded Derby database -->
        <journaledJDBC journalLogFiles="5"
                       dataDirectory="/server/bea/weblogic920/domains/jms/activemq-data"/>
      <!-- Use this with the WebLogicDataSource below to use a WebLogic
           database connection pool instead of the embedded Derby database
        <journaledJDBC journalLogFiles="5"
                       dataDirectory="/server/bea/weblogic920/domains/jms/activemq-data"
                       dataSource="#WebLogicDataSource" />

      -->
    </persistenceAdapter>
  
    <transportConnectors>
        <transportConnector name="MyBrokerTCP" uri="tcp://0.0.0.0:61616" />
    </transportConnectors>
  </broker>

  <bean id="WebLogicSecurity"
        class="com.example.activemq.weblogic.ActiveMQToWebLogicSecurity">
      <property name="authorizedGroup" value="ActiveMQUsers" />
  </bean>

<!-- Uncomment and configure this if you want to use a WebLogic database
     connection pool for persistent messages
  <bean id="WebLogicDataSource"
        class="org.springframework.jndi.JndiObjectFactoryBean">
     <property name="jndiName" value="db/pool/jndi/name"/>
  </bean>
-->
</beans>

Network of Brokers (Broker 1/2)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://activemq.org/config/1.0">
  <!-- Allows us to use system properties as variables in this configuration file -->
  <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
  
  <broker useJmx="true" brokerName="FirstBroker" useShutdownHook="false"
          plugins="#WebLogicSecurity">

    <!-- Register all ActiveMQ Classic MBeans with the WebLogic runtime MBeanServer -->
    <managementContext>
      <managementContext>
          <MBeanServer>
             <bean class="org.springframework.jndi.JndiObjectFactoryBean" xmlns="">
                <property name="jndiName" value="java:comp/env/jmx/runtime" />
                <property name="lookupOnStartup" value="true" />
                <property name="expectedType" value="javax.management.MBeanServer" />
             </bean>
          </MBeanServer>
      </managementContext>
    </managementContext>
  
    <persistenceAdapter>
      <!-- By default, use an embedded Derby database -->
        <journaledJDBC journalLogFiles="5"
                       dataDirectory="/server/bea/weblogic920/domains/jms/activemq-b1-data"/>
      <!-- Use this with the WebLogicDataSource below to use a WebLogic
           database connection pool instead of the embedded Derby database
        <journaledJDBC journalLogFiles="5"
                       dataDirectory="/server/bea/weblogic920/domains/jms/activemq-b1-data"
                       dataSource="#WebLogicDataSource" />

      -->
    </persistenceAdapter>
  
    <transportConnectors>
        <transportConnector name="FirstBrokerTCP" uri="tcp://0.0.0.0:60010" />
    </transportConnectors>
    
    <networkConnectors>
        <networkConnector name="Broker1ToBroker2"
                          uri="static://(tcp://localhost:60011)" failover="true"
                          userName="fixme" password="fixme"/>
    </networkConnectors>
  </broker>

  <bean id="WebLogicSecurity"
        class="com.example.activemq.weblogic.ActiveMQToWebLogicSecurity">
      <property name="authorizedGroup" value="ActiveMQUsers" />
  </bean>

<!-- Uncomment and configure this if you want to use a WebLogic database
     connection pool for persistent messages
  <bean id="WebLogicDataSource"
        class="org.springframework.jndi.JndiObjectFactoryBean">
     <property name="jndiName" value="db/pool/jndi/name"/>
  </bean>
-->
</beans>

Network of Brokers (Broker 2/2)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://activemq.org/config/1.0">
  <!-- Allows us to use system properties as variables in this configuration file -->
  <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
  
  <broker useJmx="true" brokerName="SecondBroker" useShutdownHook="false"
          plugins="#WebLogicSecurity">

    <!-- Register all ActiveMQ Classic MBeans with the WebLogic runtime MBeanServer -->
    <managementContext>
      <managementContext>
          <MBeanServer>
             <bean class="org.springframework.jndi.JndiObjectFactoryBean" xmlns="">
                <property name="jndiName" value="java:comp/env/jmx/runtime" />
                <property name="lookupOnStartup" value="true" />
                <property name="expectedType" value="javax.management.MBeanServer" />
             </bean>
          </MBeanServer>
      </managementContext>
    </managementContext>
  
    <persistenceAdapter>
      <!-- By default, use an embedded Derby database -->
        <journaledJDBC journalLogFiles="5"
                       dataDirectory="/server/bea/weblogic920/domains/jms/activemq-b2-data"/>
      <!-- Use this with the WebLogicDataSource below to use a WebLogic
           database connection pool instead of the embedded Derby database
        <journaledJDBC journalLogFiles="5"
                       dataDirectory="/server/bea/weblogic920/domains/jms/activemq-b2-data"
                       dataSource="#WebLogicDataSource" />

      -->
    </persistenceAdapter>
  
    <transportConnectors>
        <transportConnector name="SecondBrokerTCP" uri="tcp://0.0.0.0:60011" />
    </transportConnectors>
    
    <networkConnectors>
        <networkConnector name="Broker2ToBroker1"
                          uri="static://(tcp://localhost:60010)" failover="true"
                          userName="fixme" password="fixme" />
    </networkConnectors>
  </broker>

  <bean id="WebLogicSecurity"
        class="com.example.activemq.weblogic.ActiveMQToWebLogicSecurity">
      <property name="authorizedGroup" value="activemq" />
  </bean>

<!-- Uncomment and configure this if you want to use a WebLogic database
     connection pool for persistent messages
  <bean id="WebLogicDataSource"
        class="org.springframework.jndi.JndiObjectFactoryBean">
     <property name="jndiName" value="db/pool/jndi/name"/>
  </bean>
-->
</beans>

Log4J Configuration File (log4j.properties)

# Can change this to "INFO, out" or "INFO, out, stdout"
# to enable logging to the file defined down below
log4j.rootLogger=INFO, stdout
log4j.logger.org.apache.activemq.spring=WARN
log4j.logger.org.springframework=WARN
log4j.logger.org.apache.xbean.spring=WARN

# Configuration to log to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-5p %-30.30c{1} - %m%n
log4j.appender.stdout.threshold=INFO

# Configuration for a log file (in addition to or instead of stdout)
log4j.appender.out=org.apache.log4j.RollingFileAppender
log4j.appender.out.file=/server/bea/weblogic920/domains/test/activemq.log
log4j.appender.out.maxFileSize=1024KB
log4j.appender.out.maxBackupIndex=5
log4j.appender.out.append=true
log4j.appender.out.layout=org.apache.log4j.PatternLayout
log4j.appender.out.layout.ConversionPattern=%d \[%-15.15t\] %-5p %-30.30c{1} - %m%n

Installation Procedure

This procedure makes the following assumptions:

  • The ActiveMQ Classic configuration file and Log4J configuration file will be stored in a subdirectory of the WebLogic domain directory for ease of editing. They may be packaged into WEB-INF/classes in the WAR for ease of distribution instead.
  • The ActiveMQ Classic JMX management features will be exposed via the WebLogic runtime JMX MBeanServer. This is not required, but it should allow existing WebLogic management scripts to see the ActiveMQ Classic MBeans. NOTE: Additional configuration is required if the Sun JVM JMX server or JRockit management server will be used instead, or if the embedded ActiveMQ Classic JMX server will be used instead and more than one ActiveMQ Classic instance will be run on the same server.
  • ActiveMQ Classic will be installed on a single WebLogic instance or on two WebLogic instances in a Network-of-Brokers configuration.
    • In a (Network-of-Brokers) cluster, the two ActiveMQ Classic instances will use specific URLs to locate each other, rather than attempting runtime discovery of arbitrary brokers that may be present on the network.
  • Either ActiveMQ Classic security is disabled, or ActiveMQ Classic logins are validated against the WebLogic default security realm and a login is required and any member of a designated WebLogic group can access ActiveMQ Classic.

Prerequisites

  • WebLogic Express 9.2 has been installed
  • A simple WebLogic domain has been created
  • If the JRockit VM will be used on Linux, the file handle limit of the user running WebLogic may be important (test with ulimit -n). A recommended value would be at least twice the expected maximum number of JMS clients.
  • The ActiveMQ Classic web application WAR (activemq-4.0.1-web.war)
  • The ActiveMQ Classic configuration file (activemq-config.xml)
  • The Log4J configuration file (log4j.properties)

Installation Procedure

  1. Create a subdirectory of the WebLogic domain directory to hold ActiveMQ Classic config files (e.g. domain-dir/activemq/config)
  2. Create a subdirectory of the WebLogic domain directory to hold ActiveMQ Classic runtime data – persistent messages, etc. (e.g. domain-dir/activemq/data)
  3. Edit the activemq-config.xml to point to the correct runtime data directory created in step 2 (look for the part of the file that reads dataDirectory="...")
  4. In activemq-config.xml, review the port for the current ActiveMQ Classic server defined in the <transportConnector .../> line, if ActiveMQ Classic clustering will be used, review the hostname and port for the other ActiveMQ Classic server(s) in the cluster defined in the <networkConnector .../> line.
  5. If ActiveMQ Classic clustering and security are both enabled, in activemq-config.xml, find (or add) the userName and password settings on the <networkConnector .../> and change them to valid values. (When security is enabled, the ActiveMQ Classic brokers in a cluster require valid logins to connect to each other to form the cluster.)
  6. If security is enabled, in activemq-config.xml, find the authorizedGroup setting on the WebLogicSecurity bean and set that to the name of the WebLogic group whose members should be able to access ActiveMQ Classic. Note that the account used by the network connectors in the previous step must be members of this group. (This entry in the config file is described in the previous section)
  7. (Optional) Update the log4j.properties file to save ActiveMQ Classic logs to a file rather than just emitting to the WebLogic server’s standard output (e.g. change the first line to log4j.rootLogger=INFO, out, stdout and change the destination file in the log4j.appender.out.file=... line)
  8. Save the activemq-config.xml and log4j.properties files to the ActiveMQ Classic configuration directory created in step 1
  9. Edit the startWebLogic.sh file in the domain directory and add the following line to the top (immediately after the DOMAIN_HOME=... line), adjusting the line to use the directory created in step 1:
    export EXT_POST_CLASSPATH=${DOMAIN_HOME}/activemq/config
    
  10. Start WebLogic
  11. Deploy the activemq-4.0.1-web.war file, by copying it to the domain-dir/autodeploy directory or using the deployment tools in the WebLogic console.
  12. Verify that the WebLogic server standard output (or the ActiveMQ Classic log file configured in step 5) shows that ActiveMQ Classic started, with output like this:
    INFO  BrokerService                  - ActiveMQ 4.0.1 JMS Message Broker (localhost) is starting
    INFO  BrokerService                  - For help or more information please see:
                                           http://incubator.apache.org/activemq/
    INFO  JDBCPersistenceAdapter         - Database driver recognized: \[apache\_derby\_embedded\_jdbc\_driver\]
    INFO  JournalPersistenceAdapter      - Journal Recovery Started from: Active Journal: using 5 x 20.0 Megs at:
                                           /data/server/bea/weblogic920/domains/test/activemq-data/journal
    INFO  JournalPersistenceAdapter      - Journal Recovered: 0 message(s) in transactions recovered.
    INFO  TransportServerThreadSupport   - Listening for connections at: tcp://0.0.0.0:60010
    INFO  TransportConnector             - Connector default Started
    INFO  BrokerService                  - ActiveMQ JMS Message Broker
                                           (localhost, ID:remus-28763-1156532531109-1:0) started
    
  13. Test a management connection by running the jconsole tool distributed with Java 5, using an advanced connection, entering the URL service:jmx:rmi:///jndi/iiop://localhost:7001/weblogic.management.mbeanservers.runtime (adjusting localhost:7001 to the WebLogic server hostname and port) and the WebLogic administrator username and password. Once connected, on the MBeans tab, there should be entries under org/activemq
  14. Test a security if desired by running the example producer and consumer from an ActiveMQ Classic 4.0.1 distribution. Note that the connect URL is in examples/build.xml while the connect username and password need to be added to examples/src/ConsumerTool.java and examples/src/ProducerTool.java to connect successfully to a secure instance.
  15. If ActiveMQ Classic clustering will be used, repeat this process for the other WebLogic/ActiveMQ Classic instance in the cluster. This should set up the two ActiveMQ Classic servers to connect to each other. Confirm this by looking for output like this once both brokers are running:
    INFO  DemandForwardingBridge         - Network connection between vm://FirstBroker#0 and
                                           tcp://localhost:63222(SecondBroker) has been established.
    

Apache, ActiveMQ, Apache ActiveMQ, the Apache feather logo, and the Apache ActiveMQ project logo are trademarks of The Apache Software Foundation. Copyright © 2024, The Apache Software Foundation. Licensed under Apache License 2.0.