Using ActiveMQ, Generic JMS RA and SJSAS (Glassfish)
This document is my notes on making ActiveMQ and SJSAS work together using GenericJMSRA. The objectives is to make ActiveMQ as the JMS provider and MDB can be deployed in SJSAS, listening messages from ActiveMQ. Please note that, the SJSAS version I use is 9.0 Update 1. I don't have time to test it with SJSAS 9.1 or Glassfish v2.
First, download all binaries:
- genericra 1.7 (rar)
- activemq 4.1.1 (zip or tar.gz)
The activemq have some dependencies, however, you can easily found all of them in the distribution (the zip or tar.gz). The following is list of minimum dependencies:
In order to use genericra you need to first create a resource adapter config using asadmin (Command line tools of SJSAS).
You should note that, the above command should executed as one single line and no space around ':'. Just like:
Under DOS prompt, you should use ONLY ONE '/' to do espcape, like this.
Package your application, genericra.rar and activemq dependencies in one single EAR. The structure of the EAR should like this:
Inside the mymodules.jar (where I put my MDB), the sun-ejb-jar.xml should look like this:
And the application.xml should look like this:
Deploy the genericra:
Create connection pool. Run the following command in one single line:
Create connection factory admin object. Run the following command in one single line, note that, "jms/SimpleQueueConnectionFactory" need to match in your sun-ejb-jar.xml:
Classloader / commons-logging+log4j issue
In the procedure shown above, you should notice one thing, ie, the RA, ActiveMQ and my MDB is deployed as one single EAR. You can deploy the genericra standalone without putting it into the ear, provided that you are not using commons-logging and log4j (directly or indirectly).
In the application I'm working on, commons-logging is used, and ActiveMQ also use commons-logging. In SJSAS, connector classloader is parent of the application classloader, as a result, if you deploy genericra independently, and then you deploy your application, log4j.xml will never get loaded except you put your application log4j.xml along with the ActiveMQ jars.
With Java standard classloading procedure, classloader will first delegate the loading to parent. When application classloader lookup the LogFactory class, it will first delegate to its parent classloader (ie the connector classloader). As the connector classloader have loaded ActiveMQ and its dependencies (which include commons-logging), LogFactory will finally loaded by the connector classloader. When commons-logging try to initialize the LogFactoryImpl, and hence trigger the standard procedure of log4j initialization, log4j configuration (log4j.xml or log4j.properties) in your application will not get loaded (as log4j logger is loaded by connector classloader).
As a result, deploy genericra independently is not the perfect solution in this case.
Luckily, with some advice from Glassfish forum (thanks Sivakumar), I worked out a better solution, ie, packaged all things (including genericra and activemq) into one EAR. When packaged in this way, all classes will be loaded under one classloader, and the good thing is, you can put your log4j.xml within one of the your jar (ie, the normal way!).
However, you should note one minor point, deploying genericra standalone and packaged with the EAR have one minor difference. If you deploy the RA with EAR, you need to reference the RA using the format 'appName#raName'. As a result, the reference name of the RA is myapp#genericra (see create-resource-adapter-config and sun-ejb-jar.xml part).
If you deploy the RA independently, the ra name is just genericra (as shown in the example by Ramesh).
In the instruction described above, LocalTransaction is used. (SupportsXA=false and --transactionsupport LocalTransaction) as I am currently using Non-XA transaction, however, as example shown by Ramesh, XA should also work.
When you create the resource-adapter-config, there is two way to configure. One way is using JNDI, another way is using JavaBean introspection feature of genericra. In the example above, I go with JavaBean introspection feature (so 'ProviderIntegrationMode=javabean'). For more details on this, please checkout the user guide of genericra. Also, I found that expample provided on the genericra website is also valuable resource.