Setting up a JMS bridge between Weblogic and ActiveMQ

Almost four years ago, I wrote about how to setup a JMS bridge between Weblogic and HornetQ. Lately, I’ve had to research how to do the same work with ActiveMQ. Here you have my findings. As it was for HornetQ, the first step was to copy the client libraries to a folder residing in a filesystem of my Weblogic server, in the case of ActiveMQ these files are:

  • activemq-client-5.10.0.jar
  • hawtbuf-1.10.jar
  • slf4j-api-1.7.5.jar

Later on, I set the PRE_CLASSPATH variable pointing it to these libraries into the script setDomainEnv. Creating messaging destinations is more or less the same job as it was for HornetQ, you just have to change the initial context factory and connection url parameters:

<jms-bridge-destination>
  <name>JMS Bridge Destination-Target</name>
  <adapter-jndi-name>eis.jms.WLSConnectionFactoryJNDIXA</adapter-jndi-name>
  <user-name>testUser</user-name>
  <user-password-encrypted>{AES}GZTa15osrQW6/5rbE2fzm+a9BX/YPY7Hm3xiIFi0oMQ=</user-password-encrypted>
  <classpath></classpath>
  <connection-factory-jndi-name>jms/TestXAQueueConnectionFactory</connection-factory-jndi-name>
  <initial-context-factory>org.apache.activemq.jndi.ActiveMQInitialContextFactory</initial-context-factory>
  <connection-url>tcp://localhost:61616</connection-url>
  <destination-jndi-name>jms/TestQueue</destination-jndi-name>
  <destination-type>Queue</destination-type>
</jms-bridge-destination>

But the former configuration is not enough, because ActiveMQ hasn’t his own JNDI provider (I had ActiveMQ as a JMS provider for a ServiceMix ESB) and requires a jndi.properties file with the mappings between physical destinations and tha jndi ones, but, how to configure the properties file in the context of a Weblogic messaging bridge? Here is the trick: create a JAR archive containing the jndi.properties file and put the JAR in the CLASSPATH (the same way at it was described before for activemq-client-5.10.0.jar). The steps to create the JAR archive are:

  • Create a file called jndi.properties with the following entries:

connectionFactoryNames=ConnectionFactory,XAConnectionFactory queue.TestQueue=TestQueue

  • Create the archive with the following command:

jar cvf jndi.jar jndi.properties

I found this trick in this post, after have tested many different configurations, including the setup of a Weblogic Foreign JMS Server, without success. Finally, I’d like to point out that I am not completely happy with this setup because it has an obvious drawback: you have modify and redeploy the jndi.jar archive every time you add a new queue or topic, so suggestions are welcome!!!


References


Java EE sample

Last Thursday, March 27th, 2014, I offered a talk called “Introduction to Java EE”, as part of our local developers group’s event, Betabeers. It was an amazing experience for me.

20140327BetabeersI started off with a short theoretical introduction. Later on, I briefly showed some of the API of Java EE through a small CRUD sample application for registering ship data. I talked about JPA, EJB, Bean Validation, JSF, Managed Beans, JAX-RS and JAAS.

Here you have the PowerPoint that supported my presentation:


Working with Oracle XMLType and JPA over Weblogic

I’ve been working with the object type of Oracle databases for XML for a long time, but always in the context of PL/SQL programming. Last week,  I developed a Java EE module that made use of JPA entities, supported by tables with SYS.XMLType columns, so I’d like to share my findings with an example.

First of all, here you have the creation sentence of a table that offers persistence to a simple messaging interface:


create table messages
  (
    message_id     number  constraint message_pk primary key,
    reception_date date    not null,
    msg_content    xmltype not null 
                           constraint message_msg_content_ck check(
                              xmlisvalid(msg_content) = 1)
  )
  xmltype column msg_content store as clob xmlschema
  "http://testdomain.com/Messages.xsd"
  element "Messages";

This is an excerpt of a JPA entity that could represent the former table:


package com.wordpress.fcosfc.test.messaging;

...

import org.eclipse.persistence.annotations.Customizer;

@Entity
@Table(name = "MESSAGES")
@Customizer(XMLTypeAttributeCustomizer.class)
public class Messages implements Serializable {

    @Id
    @Column(name = "MESSAGE_ID", nullable = false)
    private BigDecimal messageId;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "RECEPTION_DATE", nullable = false)
    private Date receptionDate;

    @Lob
    @Column(nullable = false, name ="msg_content")    
    private String msgContent;

    ...
}

I’m sure you’ve realized that there is an special annotation Customizer, which makes reference to this class:


package com.wordpress.fcosfc.test.messaging;

import org.eclipse.persistence.config.DescriptorCustomizer;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.mappings.xdb.DirectToXMLTypeMapping;

public class XMLTypeAttributeCustomizer implements DescriptorCustomizer {

    @Override
    public void customize(final ClassDescriptor descriptor) throws Exception {
        descriptor.removeMappingForAttributeName("msg_content");
        final DirectToXMLTypeMapping mapping = new DirectToXMLTypeMapping();
        mapping.setAttributeName("msg_content");
        mapping.setFieldName("MSG_CONTENT");
        mapping.getField().setColumnDefinition("sys.XMLTYPE");
        descriptor.addMapping(mapping);
    }

}

This class has a method that changes the default mapping of the EclipseLink JPA provider in order to use the proper type from Oracle: SYS.XMLType.

Finally, I’d like to point out that the first time I deployed my module over an Oracle Weblogic 10.3.5 application server I got a ClassNotFoundException: oracle/xdb/xmltype , so I had to extend my Weblogic domain in order to support Oracle XMType. Here you have my reference about how to do it, I just followed the instructions to support Oracle XDB.


References


Fighting with sockets!

Last week, I was appointed to develop a Java program that should connect to an external secure socket, in order to get data provided by a partner company. Another requisite was that the module should be stored on an Oracle 11g Database, so I must use a 1.5 JDK. Easy, I thought!

First of all, I review Java Secure Socket Extension (JSSE) Reference Guide. Our company partner IT team provided me with the key store containing the certificate I should trust and I decide to program a custom SSL context:

   ...
   KeyStore keyStoreTrust = KeyStore.getInstance("PKCS12");
   keyStoreTrust.load(this.getClass().getResourceAsStream("KeyStoreTrust.pfx"),
                      "password".toCharArray());
   TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX");
   trustManagerFactory.init(keyStoreTrust);

   SSLContext sslContext = SSLContext.getInstance("SSL");
   sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
   ...

The first problem arose when the server socket (developed in Microsoft .NET C#) unexpectedly closed the connection during the handshake, the support guy of my partner company said me that they got the following error message: “The client and server cannot communicate, because they do not possess a common algorithm”. Therefore, I delved into the problem and finally I realized that the server wanted to use a TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA cipher suite, which wasn’t supported by the security providers shipped with the JDK 1.5 I’d like to point out that a key point to find out the source of the error was to activate the debug of the SSL connection:

System.setProperty("javax.net.debug", "ssl");

Hence, I decided to add to my program the well-known Bouncy Castle security provider, which supports the required cipher suite and it’s 1.5 compliant:

Security.addProvider(new BouncyCastleProvider());

Once I sorted out the problem, everything started to work properly, at least as an stand-alone client! So, I created a “Loadjava and Java Stored Procedures” profile in my JDeveloper IDE, in order to deploy the software to the Oracle Database 11.2, but when I tried to do it I got the following errors:

Invoking loadjava on connection 'Test11g_Paco' with arguments:
 -order -resolve -definer -thin -resolver ((* TEST) (* PUBLIC) (* -)) -synonym
 errors   : class org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey
 ORA-29552: verification warning: java.lang.NoClassDefFoundError: java/security/interfaces/ECPrivateKey

 errors   : class org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey
 ORA-29552: verification warning: java.lang.NoClassDefFoundError: java/security/interfaces/ECPublicKey

 errors   : class org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey
 ORA-29552: verification warning: java.lang.NoClassDefFoundError: java/security/interfaces/ECPrivateKey

 errors   : class org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PublicKey
 ORA-29552: verification warning: java.lang.NoClassDefFoundError: java/security/interfaces/ECPublicKey

 errors   : class org/bouncycastle/jce/provider/JCEECPrivateKey
 ORA-29552: verification warning: java.lang.NoClassDefFoundError: java/security/interfaces/ECPrivateKey

 errors   : class org/bouncycastle/jce/provider/JCEECPublicKey
 ORA-29552: verification warning: java.lang.NoClassDefFoundError: java/security/interfaces/ECPublicKey

 Loadjava finished.

I can’t understand the problem because the interfaces java.security.interfaces.ECPublicKey and java.security.interfaces.ECPrivateKey are available in 1.5 and the Oracle Database 11.2 JVM is supposed to be 1.5 compliant, but I couldn’t find any satisfactory solution.


Tracking of a Weblogic JMS bridge

I’ve been talking about JMS bridges between Weblogic and HornetQ for a while, today I’d like to deal with the issue of tracking, which is especially useful when you need to know the time when a message was dispatched to the destination system.

The idea is to configure Weblogic to debug messaging bridge runtime events, add a custom logging handler that captures and saves these events into a table and to analyze them, in order to track the pass of the messages through the bridge.

Therefore, the first task is to enable the debugging of the messaging bridge events in Weblogic. One of the methods to achieve this goal is to add the following lines to the setDomainEnv.cmd script:

set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.debug.DebugMessagingBridgeStartup=true
set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.debug.DebugMessagingBridgeRuntime=true

The next step is to create a table to give persistence to the events:

CREATE TABLE wl_log
(log_id        NUMBER              CONSTRAINT wl_log_pk PRIMARY KEY,
 log_timestamp TIMESTAMP           NOT NULL,
 msg_id        VARCHAR2(25 CHAR)   NOT NULL,
 log_level     VARCHAR2(25 CHAR)   NOT NULL,
 subsystem     VARCHAR2(50 CHAR)   NOT NULL,
 message       VARCHAR2(4000 CHAR) NOT NULL);

CREATE SEQUENCE wl_log_s
INCREMENT BY 1
START WITH 1
MAXVALUE 999999999999
MINVALUE 1
CACHE 20;

The following task is to create a custom logging handler that will capture and save the events into the former table (this class has references to a properties file, where I put the parameters needed to connect to the Oracle database):

public class WLCustomLoggingHandler extends Handler {
    private Connection dbConn = null;
    private PreparedStatement psmt = null;

    public WLCustomLoggingHandler() throws IOException,
                                           ClassNotFoundException,
                                           SQLException {
        super();

        Properties dbProperties;

        dbProperties = new Properties();
        dbProperties.load(this.getClass().getResourceAsStream(
                                            "WLCustomLoggingHandlerDB.properties"));
        Class.forName(dbProperties.getProperty("DRIVER"));
        this.dbConn =
                DriverManager.getConnection(dbProperties.getProperty("URL"),
                                            dbProperties.getProperty("USER"),
                                            dbProperties.getProperty("PASS"));
        this.psmt =
                this.dbConn.prepareStatement("INSERT INTO wl_log " +
                                             "(log_id, log_timestamp, msg_id, " +
                                             "log_level, subsystem, message) " +
                                             "VALUES(wl_log_s.nextval, ?, ?, ?, ?, ?)");

        this.setErrorManager(new ErrorManager() {
            public void error(String msg, Exception ex, int code) {
                System.err.println("Error reported by TestWLLoggingHandler "
                                   + msg + ex.getMessage());
                LoggingHelper.getServerLogger().removeHandler(WLCustomLoggingHandler.this);
            }
        });
    }

    @Override
    public void publish(LogRecord record) {
        WLLogRecord wlLogRecord = (WLLogRecord)record;
        if (this.isLoggable(wlLogRecord)) {
            try {
                psmt.setEscapeProcessing(true);
                psmt.setTimestamp(1, new Timestamp(wlLogRecord.getMillis()));
                psmt.setString(2, wlLogRecord.getId());
                psmt.setString(3, wlLogRecord.getLevel().getName());
                psmt.setString(4, wlLogRecord.getLoggerName());
                psmt.setString(5, wlLogRecord.getMessage());
                psmt.executeUpdate();
                this.flush();
            } catch (SQLException ex) {
                this.reportError("WLCustomLoggingHandlerpublish: ",
                                 ex,
                                 ErrorManager.WRITE_FAILURE);
            }
        }
    }

    @Override
    public void flush() {
        try {
            this.dbConn.commit();
        } catch (SQLException ex) {
            this.reportError("WLCustomLoggingHandlerflush: ",
                             ex,
                             ErrorManager.FLUSH_FAILURE);
        }
    }

    @Override
    public void close() throws SecurityException {
        try {
            this.dbConn.close();
        } catch (SQLException ex) {
            this.reportError("WLCustomLoggingHandlerclose: ",
                             ex,
                             ErrorManager.CLOSE_FAILURE);
        }
    }
}

We just want to analyze the events regarding to the messaging bridge, so we have to create a logging filter:

public class WLCustomLoggingFilter implements Filter {
    public WLCustomLoggingFilter() {
        super();
    }

    @Override
    public boolean isLoggable(LogRecord record) {
        if (record instanceof WLLogRecord) {
            WLLogRecord wlLogRecord = (WLLogRecord)record;

            return wlLogRecord.getSubsystem().equals("MessagingBridge") ||
                wlLogRecord.getSubsystem().equals("MessagingBridgeRuntime");
        } else {
            return false;
        }
    }
}

The next step is to code a Weblogic startup class:

public class WLCustomLoggingHandlerStartupClass {
    public WLCustomLoggingHandlerStartupClass() {
        super();
    }

    public void configureLogger() {
        Logger logger = null;
        Handler handler = null;

        try {
            logger = LoggingHelper.getServerLogger();
            handler = new WLCustomLoggingHandler();
            handler.setFilter(new WLCustomLoggingFilter());
            logger.addHandler(handler);
        } catch (Exception ex) {
            System.err.println("WLCustomLoggingHandlerStartupClass.configureLogger: "
                               + ex.getMessage());
            ex.printStackTrace();
            try {
                logger.removeHandler(handler);
            } catch (Exception ignore) {
            }
        }
    }

    public static void main(String[] args) {
        WLCustomLoggingHandlerStartupClass testWLCustomLoggingHandlerStartupClass =
            new WLCustomLoggingHandlerStartupClass();
        testWLCustomLoggingHandlerStartupClass.configureLogger();
    }
}

This class has to be configured in Weblogic by going to the Enviroment->Startup and Shutdown Classes of the console (obviously, the corresponding jar file containing the former code has to be available on the weblogic classpath):

Weblogic Startup and Shutdown Classes
The last step is to analyze the log entries in order to know when each message is dispatched to its destination, when the bridge was up and running, etc. MessagingBridge Subsystem Messages are helpful to achieve this goal, especially:

  • BEA-200028: The bridge “arg01” has started transferring messages.
  • BEA-200024: Bridge “arg0” refused to obtain connections and transfer any messages, because it has been stopped or suspended, or is shutting down.
  • BEA-200015: An error occurred in bridge “arg0” during the transfer of messages (e).

But, the pass of a message through a bridge has to be discovered by analyzing the log entries with id BEA-000000, of course the sender program has to save the message and its ID on persistent storage at the time it sends it. The bridge dequeues each message from the source and enqueues it to the destination, all in the context of a XA batch transaction (10 messages by default):

03/03/12 10:12:11,859000000	"Bridge: TestBridge (processMessages()) received message:
                                 JMS Message Class: TextMessage
                                 JMSMessageID: ID:B3AD885BC54B4391976BEDA9EC00E8F4
                                 JMSCorrelationID: null
                                 JMSDeliveryMode: PERSISTENT
                                 JMSDestination: TestQueue
                                 JMSExpiration: 0
                                 JMSPriority: 8
                                 JMSRedelivered: false
                                 JMSReplyTo: null
                                 JMSTimestamp: 1330851452000 (Sun Mar 04 09:57:32 CET 2012)
                                 JMSType: null
                                 Transaction Id: BEA1-00018D19CC5B9E472B1E
                                 This is a test message: 010"
03/03/12 10:12:11,859000000	"Bridge: TestBridge (processMessages()) successfully sent message:
                                 JMS Message Class: TextMessage
                                 Old JMS MessageID: ID:B3AD885BC54B4391976BEDA9EC00E8F4
                                 New JMS MessageID: ID:2064fac7-65da-11e1-9824-005056c00008
                                 This is a test message: 010"
03/03/12 10:12:12,671000000	Bridge: TestBridge (processMessages()) committed the transaction

References


Securing a JMS bridge between Weblogic and HornetQ

I posted my notes about setting up a JMS bridge between Weblogic and HornetQ last September, now I’d like to talk about how to secure the connection: implementing an user authentication & authorization process and ensuring the communication between the servers with SSL. Finally, I’ll write about accessing to the secured queue from a Message Driven Bean (MDB) deployed on JBoss 6.1.  Most of the configuration is made on HornetQ, therefore I’ll make references to its User Manual.

The first step was to set up a security constraint, in order to ensure that just the user assigned to Weblogic 10.3 for the bridge could access to the queue of HornetQ. I had previously created a security role (testRole) and a user (testUser) belonging to it on JBoss, the procedure to do this may be different, depending on the security manager you’re using, and it’s out of the scope of this post. I used the defaults for testing purposes and just had to write a line in the files %JBOSS_HOME%\server\default\conf\props\hornetq-users.properties and %JBOSS_HOME%\server\default\conf\props\hornetq-roles.properties  Once I configured the user and the role, I edited the file %JBOSS_HOME%\ server\default\deploy\hornetq\hornetq-configuration.xml and added the following security setting:

<security-setting match="jms.queue.TestQueue">
  <permission type="consume" roles="testRole"/>
  <permission type="send" roles="testRole"/>
</security-setting>

Please, read the security chapter of the HornetQ User Manual to know about the different permissions that can be defined, addressing and wildcards.

The next step was to modify the Weblogic bridge destination on the console, in order to set up the user assigned by JBoss, here you have the excerpt from the resulting config.xml file:

<jms-bridge-destination>
  <name>JMS Bridge Destination-Target</name>
  <adapter-jndi-name>eis.jms.WLSConnectionFactoryJNDIXA</adapter-jndi-name>
  <user-name>testUser</user-name>
  <user-password-encrypted>{AES}GZTa15osrQW6/5rbE2fzm+a9BX/YPY7Hm3xiIFi0oMQ=</user-password-encrypted>
  <classpath></classpath>
  <connection-factory-jndi-name>jms/TestXAQueueConnectionFactory</connection-factory-jndi-name>
  <initial-context-factory>org.jnp.interfaces.NamingContextFactory</initial-context-factory>
  <connection-url>jnp://srvhornetq.test.local:1099</connection-url>
  <destination-jndi-name>jms/TestQueue</destination-jndi-name>
  <destination-type>Queue</destination-type>
</jms-bridge-destination>

The following issue was to secure the traffic between Weblogic and the JBoss server, where HornetQ was running as a JMS provider. To accomplish that goal, it was very useful to read the chapter about transport of the HornetQ User Manual. A previous task at this point was to prepare a self-signed certificate using keytool, the sentence I executed to create the client keystore was:

keytool -genkeypair -alias test -keyalg RSA -keysize 1024 -dname OU=TEST,CN=TEST,CN=LOCAL
        -keypass test1234 -keystore hornetq.test.keystore -storepass test1234

In order to create the trust keystore, I simply imported the client keystore into a new one:

keytool -importkeystore -srckeystore hornetq.test.keystore -destkeystore
         hornetq.test.truststore -srcstorepass test1234 -deststorepass test1234

I put these two keystores into the %JBOSS_HOME%\server\default\data\hornetq directory, so the acceptor that listens for SSL connections, could access them. I also copied the hornetq.test.keystore to the file system of Weblogic, in order to be accessed by the connector. Here you have an excerpt from the hornetq-configuration.xml file:

<connectors>
...
  <connector name="netty-ssl-connector">
    <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class>
    <param key="host" value="${jboss.bind.address:localhost}"/>
    <param key="port" value="${hornetq.remoting.netty.port.ssl:5446}"/>
    <param key="ssl-enabled" value="true"/>
    <param key="key-store-path" value="/oracle/hornetq/hornetq/hornetq.test.keystore"/>
    <param key="key-store-password" value="test1234"/>
  </connector>
...
</connectors>

<acceptors>
...
  <acceptor name="netty-ssl-acceptor">
    <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
    <param key="host" value="${jboss.bind.address:localhost}"/>
    <param key="port" value="${hornetq.remoting.netty.port.ssl:5446}"/>
    <param key="ssl-enabled" value="true"/>
    <param key="key-store-path" value="${jboss.server.data.dir}/hornetq/hornetq.test.keystore"/>
    <param key="key-store-password" value="test1234"/>
    <param key="trust-store-path" value="${jboss.server.data.dir}/hornetq/hornetq.test.truststore"/>
    <param key="trust-store-password" value="test1234"/>
  </acceptor>
...
</acceptors>

Finally, I deployed a MDB on JBoss that listened for the messages send from an application running on Weblogic:

@MessageDriven(name = "TestMDB", activationConfig = {
  @ActivationConfigProperty(propertyName = "acknowledgeMode",
                            propertyValue = "Auto-acknowledge"),
  @ActivationConfigProperty(propertyName = "destinationType",
                            propertyValue = "javax.jms.Queue"),
  @ActivationConfigProperty(propertyName = "destination",
                            propertyValue = "jms/TestQueue")
})
public class TestMDB implements MessageListener {
  static final Logger logger = Logger.getLogger("TestMDB");

  public void onMessage(Message message) {
    TextMessage msg = null;

    try {
      if (message instanceof TextMessage) {
        msg = (TextMessage) message;
        logger.info("MESSAGE BEAN: Message received: " + msg.getText());
      } else {
        logger.warning("Message of wrong type: " + 
                               message.getClass().getName());
      }
    } catch (JMSException e) {
      logger.severe("TestMDB.onMessage: JMSException: " + e.toString());
      e.printStackTrace();
    } catch (Throwable te) {
      logger.severe("TestMDB.onMessage: Exception: " + te.toString());
      te.printStackTrace();
    }
  }
}

But, how to access to a secured queue? The answer was to configure the following piece with the user and password into the jboss.xml file:

<enterprise-beans>
  <message-driven>
  <ejb-name>TestMDB</ejb-name>
  <mdb-user>testUser</mdb-user>
  <mdb-passwd>test1234</mdb-passwd>
  </message-driven>
</enterprise-beans>

References



Setting up a JMS bridge between Weblogic and HornetQ

I’d like to publish my notes about how to setup a basic JMS bridge between a Weblogic Server and an instance of HornetQ, running on a JBoss 6.1 Application Server. My reference was the document “Configuring and Managing the WebLogic Messaging Bridge”.

First of all, I copied the following libraries to a folder residing in a filesystem of my Weblogic server:

  • hornetq-core-client.jar
  • hornetq-jms-client.jar
  • netty.jar
  • jnp-client.jar
  • jboss-logging.jar

Later on, I set the PRE_CLASSPATH variable pointing it to these libraries into the script setDomainEnv and started Weblogic, so I could use the console to create the source bridge destination, a typical Weblogic one, just selecting the default JNDI adapter name: eis.jms.WLSConnectionFactoryJNDIXA, and putting the JNDI name of my Connection Factory and my Queue in. Here you have an excerpt of the resulting config.xml file:

<jms-bridge-destination>
   <name>JMS Bridge Destination-Source</name>
   <adapter-jndi-name>eis.jms.WLSConnectionFactoryJNDIXA</adapter-jndi-name>
   <classpath></classpath>
   <connection-factory-jndi-name>jms/TestXAQueueConnectionFactory</connection-factory-jndi-name>
   <connection-url></connection-url>
   <destination-jndi-name>jms/TestQueue</destination-jndi-name>
</jms-bridge-destination>

After that, I created the target bridge destination, the HornetQ one (I’ve previously set up the needed objects on HornetQ, please review its user manual for further information). In addition to the JNDI names of the Connection Factory and the Queue, I had to configure the URL of the JNDI server used by the HornetQ instance, in my case jnp://srvhornetq.test.local:1099. After save the destination, I had to edit it, modify the default initial connection factory weblogic.jndi.WLInitialContextFactory to org.jnp.interfaces.NamingContextFactory, and restart the Weblogic server. The resulting piece of configuration on config.xml is:

<jms-bridge-destination>
   <name>JMS Bridge Destination-Target</name>
   <adapter-jndi-name>eis.jms.WLSConnectionFactoryJNDIXA</adapter-jndi-name>
   <classpath></classpath>
   <connection-factory-jndi-name>jms/TestXAQueueConnectionFactory</connection-factory-jndi-name>
   <initial-context-factory>org.jnp.interfaces.NamingContextFactory</initial-context-factory>
   <connection-url>jnp://srvhornetq.test.local:1099</connection-url>
   <destination-jndi-name>jms/TestQueue</destination-jndi-name>
   <destination-type>Queue</destination-type>
</jms-bridge-destination>

Finally, I setup the bridge as usual, just selecting the source and target destinations, the quality of service, etc:

<messaging-bridge>
   <name>Test-Bridge</name>
   <target>DefaultServer</target>
   <source-destination>JMS Bridge Destination- Source</source-destination>
   <target-destination>JMS Bridge Destination-Target</target-destination>
   <selector></selector>
   <quality-of-service>Exactly-once</quality-of-service>
   <started>true</started>
</messaging-bridge>

Please, be careful selecting the proper parameters for each situation, in order to avoid errors like JMS-107. For example, I recommend to create a javax.jms.XATopicConnectionFactory connection factory for a topic and a javax.jms.XAQueueConnectionFactory connection factory  for a queue, but I don’t use a generic javax.jms.XAConnectionFactory Of course, the’re a lot of issues about security, transactions, etc, but that’s the topic for another post!


References