ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

XML Messaging Using JBoss
Pages: 1, 2, 3, 4

Deployment in JBoss

The provided code for this article has been developed under Windows and Linux using:



  • Eclipse 3
  • JBoss-4.0.0
  • Quartz 1.4.2
  • Castor 0.9.5.3
  • Websphere MQ 5.3

The structure of the project file is shown in Figure 8.

Figure 8
Figure 8. Eclipse project structure

Before building the XMLConsumer and XMLProducer, you need to copy the needed .jars--the Sybase JDBC driver, the Oracle JDBC driver, Quartz, and Castor--into /server/<deploy_config>/lib.

If you use WebSphere MQ, add the following into your standardjboss.xml file:

<invoker-proxy-binding>
  <name>wsmq-message-driven-bean</name>
  <invoker-mbean>whatever</invoker-mbean>
  <proxy-factory>
     org.jboss.ejb.plugins.jms.JMSContainerInvoker
  </proxy-factory>
  <proxy-factory-config>
    <JMSProviderAdapterJNDI>WSMQProvider
    </JMSProviderAdapterJNDI>
    <ServerSessionPoolFactoryJNDI>StdJMSPool
    </ServerSessionPoolFactoryJNDI>
    <MaximumSize>15</MaximumSize>
    <MaxMessages>1</MaxMessages>
    <MDBConfig>
      <ReconnectIntervalSec>10
      </ReconnectIntervalSec>
      <DLQConfig>
        <!-- Use this for Windows 
             file system JNDI namespace -->
        <DestinationQueue>queue\\DLQ
        </DestinationQueue>
        <!-- Use this for Linux 
             file system JNDI namespace -->
        <!--DestinationQueue>queue/DLQ
        </DestinationQueue-->
        <MaxTimesRedelivered>10
        </MaxTimesRedelivered>
        <TimeToLive>0</TimeToLive>
      </DLQConfig>
    </MDBConfig>
  </proxy-factory-config>
</invoker-proxy-binding>

<container-configuration>
  <container-name>WSMQ Message Driven Bean
  </container-name>
  <call-logging>false</call-logging>
  <invoker-proxy-binding-name>
    wsmq-message-driven-bean
  </invoker-proxy-binding-name>
  <container-interceptors>
    <interceptor>
        org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor
    </interceptor>
    <interceptor>
        org.jboss.ejb.plugins.LogInterceptor
    </interceptor>
    <interceptor>
        org.jboss.ejb.plugins.RunAsSecurityInterceptor
    </interceptor>
    <!-- CMT -->
    <interceptor transaction="Container">
        org.jboss.ejb.plugins.TxInterceptorCMT
    </interceptor>
    <interceptor transaction="Container">
        org.jboss.ejb.plugins.CallValidationInterceptor
    </interceptor>
    <interceptor transaction="Container" 
            metricsEnabled="true">
        org.jboss.ejb.plugins.MetricsInterceptor
    </interceptor>
    <interceptor transaction="Container">
        org.jboss.ejb.plugins.MessageDrivenInstanceInterceptor
    </interceptor>
    <!-- BMT -->
    <interceptor transaction="Bean">
        org.jboss.ejb.plugins.MessageDrivenInstanceInterceptor
    </interceptor>
    <interceptor transaction="Bean">
        org.jboss.ejb.plugins.MessageDrivenTxInterceptorBMT
    </interceptor>
    <interceptor transaction="Bean">
        org.jboss.ejb.plugins.CallValidationInterceptor
    </interceptor>
    <interceptor transaction="Bean" 
            metricsEnabled="true">
        org.jboss.ejb.plugins.MetricsInterceptor
    </interceptor>
    <interceptor>
        org.jboss.resource.connectionmanager.CachedConnectionInterceptor
    </interceptor>
  </container-interceptors>
  <instance-pool>
    org.jboss.ejb.plugins.MessageDrivenInstancePool
  </instance-pool>
  <instance-cache></instance-cache>
  <persistence-manager></persistence-manager>
  <container-pool-conf>
    <MaximumSize>100</MaximumSize>
  </container-pool-conf>
</container-configuration>

Add the following into your jms-ds.xml file:

<mbean code="org.jboss.jms.jndi.JMSProviderLoader" 
      name="jboss.mq:service=JMSProviderLoader,
            name=WSMQProvider">
  <attribute name="ProviderName">WSMQProvider
  </attribute>
  <attribute name="ProviderAdapterClass">
    org.jboss.jms.jndi.JNDIProviderAdapter
  </attribute>
  <attribute name="QueueFactoryRef">
    QCFProducer
  </attribute>
  <attribute name="TopicFactoryRef">
    QCFProducer
  </attribute>
  <attribute name="Properties">
java.naming.factory.initial=com.sun.jndi.fscontext.RefFSContextFactory
java.naming.provider.url=file:/your-file-system-JNDI-namespace-directory
  </attribute>
</mbean>

Add the following into your META-INF/jboss.xml file:

<jboss>
  <enterprise-beans>
    <message-driven>
      <ejb-name>XMLConsumerCcyMDB
      </ejb-name>
 
      <!-- JBossMQ only -->
      <!--
      <configuration-name>
        Standard Message Driven Bean
      </configuration-name>
      <destination-jndi-name>queue/QProducer
      </destination-jndi-name>
      -->
     
      <!-- WSMQ only -->
      <configuration-name>
        WSMQ Message Driven Bean
      </configuration-name>
      <!-- Use this for Windows 
          file system JNDI namespace -->
      <destination-jndi-name>queue\\QProducer
      </destination-jndi-name> 
      <!-- Use this for Linux 
          file system JNDI namespace -->
      <!--destination-jndi-name>queue/QProducer
      </destination-jndi-name--> 
      <invoker-bindings>
        <invoker>
          <invoker-proxy-binding-name>
            wsmq-message-driven-bean
          </invoker-proxy-binding-name>
        </invoker>
      </invoker-bindings>
    </message-driven>
    ...
  </enterprise-beans>
</jboss>

Make sure you've set up the env variables as explained in pages 10-12 of the manual WebSphere MQ: Using Java (PDF). Run the following scripts:

  1. Setup/WSMQ/setupMQ.bat or Setup/WSMQ/setupMQ.sh
  2. Setup/WSMQ_FileSystemJNDI/setupJMS.bat or Setup/WSMQ_FileSystemJNDI/setupJMS.sh (amend the file system JNDI namespace directory)

Optionally, you can test if the queue created is available by running the SendAndReceive program (modify it if needed).

Note: If you define a subcontext when creating a queue within a file system JNDI namespace, the process to get the queue name is different under Windows and Linux:

  • Under Windows, you'll use queue\\QProducer.
  • Under Linux, you'll use queue/QProducer.

If you use JBossMQ, add the following to your jbossmq-destinations-service.xml file:

<mbean code="org.jboss.mq.server.jmx.Queue" 
      name="jboss.mq.destination:service=Queue,name=QProducer">
  <depends optional-attribute-name="DestinationManager">
          jboss.mq:service=DestinationManager
  </depends>
</mbean>

Steps to deploy XMLConsumer:

  1. Run the SQL set-up script, located in XMLMessaging/Setup, against the appropriate database to create the interface tables (IConsumerSybase.sql if you use Sybase for the interface tables, or IConsumserOracle.sql for Oracle).
  2. From Eclipse, configure XMLConsumer/build.properties.
  3. From Eclipse, configure XMLConsumer/src/resources/META-INF/jboss-service.xml to choose which Hibernate service you are going to use.
  4. From Eclipse, configure XMLConsumer/src/resources/META-INF/jboss.xml to choose either JBossMQ or WebSphere MQ.
  5. Build XMLConsumer to produce XMLConsumerMDB.jar and XMLConsumerService.sar.
  6. Check your JBoss server.log file (the queue QProducer must be bound).

Here is a snapshot of server.log (after formatting the line) when the consumer processes an incoming message:

14:00:00,349 INFO  [example.mdb.XMLConsumerCcyMDB] \
   === XMLConsumerCcyMDB.processXML() : invoke XMLConsumer service for Ccy
...
14:00:00,349 INFO  [example.jmx.ConsumerManager] \
   === ConsumerManager.processXML() : \
<?xml version="1.0" encoding="UTF-8"?>
<CCY>
  <CCY_DATA>
    <ORIG_CCY>EUR</ORIG_CCY>
    <SETTLED_CCY>GBP</SETTLED_CCY>
    <EFFECTIVE_FROM>07 October 2003
    </EFFECTIVE_FROM>
    <ROE>1.4339</ROE>
    <EFFECTIVE_TO>31 December 2999
    </EFFECTIVE_TO>
  </CCY_DATA>
  <CCY_DATA>
    <ORIG_CCY>USD</ORIG_CCY>
    <SETTLED_CCY>GBP</SETTLED_CCY>
    <EFFECTIVE_FROM>07 October 2003
    </EFFECTIVE_FROM>
    <ROE>1.6674</ROE>
    <EFFECTIVE_TO>31 December 2999
    </EFFECTIVE_TO>
  </CCY_DATA>
</CCY>

14:00:00,349 INFO  [example.jmx.ConsumerManager] \
   === ConsumerManager.beginTransaction()
14:00:00,349 INFO  [example.jmx.ConsumerManager] \
   === ConsumerManager.updateDataCcy() : load mapping for Castor ... 
14:00:00,600 DEBUG [example.jmx.ConsumerManager] \
   === ConsumerManager.updateDataCcy() : Hibernate\ 
   insert this : (EUR,GBP,Tue Oct 07 00:00:00 BST 2003,\
   1.4339,Tue Dec 31 00:00:00 GMT 2999) 
14:00:00,600 INFO  [STDOUT] Hibernate: \
   insert into IConsumerCcy (orig_ccy, \
   settled_ccy,  effective_from, roe, \
   effective_to) values (?, ?, ?, ?, ?)
select @@identity
14:00:00,600 DEBUG [example.jmx.ConsumerManager] \
   === ConsumerManager.updateDataCcy() : Hibernate \
   insert this : (USD,GBP,Tue Oct 07 00:00:00 BST 2003,\
   1.6674,Tue Dec 31 00:00:00 GMT 2999) 
14:00:00,600 INFO  [STDOUT] Hibernate: \
   insert into IConsumerCcy (orig_ccy, \
   settled_ccy, effective_from, roe, \
   effective_to) values (?, ?, ?, ?, ?)
select @@identity
14:00:00,610 INFO  [example.jmx.ConsumerManager] \
   === ConsumerManager.endTransaction() : Commit 
14:00:00,610 INFO  [example.jmx.ConsumerManager] \
   === ConsumerManager.endSession()

Steps to deploy XMLProducer:

  1. Run the SQL set-up scripts, located in XMLMessaging/Setup, against the appropriate databases to create the interface tables (IProducerSybase.sql and IProducerOracle.sql) and tables needed by Quartz (Quartz-sybase.sql or Quartz-oracle.sql).
  2. Configure the JBoss oracle-ds.xml and sybase-ds.xml files and deploy them.
  3. Configure XMLMessaging/Setup/quartz-service.xml, then deploy it.
  4. At this point, check your JBoss server.log file too see if a problem has been encountered.
  5. From Eclipse, configure XMLProducer/src/resources/META-INF/jboss-service.xml where appropriate (JBossMQ or WebSphere MQ, and the cron expression used by Quartz).
  6. From Eclipse, configure XMLProducer/build.properties, and then build the XMLProducer to produce XMLProducer.sar.
  7. Recheck your JBoss server.log file if you encounter problems.

Here is a snapshot of server.log (after formatting the line) when the producer sends a message:

14:00:00,199 INFO  [example.db.SybaseMessaging] \
   === SybaseMessaging.sendMsg()
14:00:00,199 INFO  [example.jmx.MOMManager] \
   === MOMManager.enqueue() 
14:00:00,199 INFO  [example.jmx.JBossMQManager] \
   === JBossMQManager.enqueue()
14:00:00,209 DEBUG [org.jboss.resource.adapter.\
   jdbc.local.LocalManagedConnectionFactory] \
   Using properties: {user=baa, password=--hidden--}
14:00:00,269 INFO  [example.jmx.JBossMQManager] \
   === Message sent : \
<?xml version="1.0" encoding="UTF-8"?>
<CCY>
  <CCY_DATA>
    <ORIG_CCY>EUR</ORIG_CCY>
    <SETTLED_CCY>GBP</SETTLED_CCY>
    <EFFECTIVE_FROM>07 October 2003
    </EFFECTIVE_FROM>
    <ROE>1.4339</ROE>
    <EFFECTIVE_TO>31 December 2999
    </EFFECTIVE_TO>
  </CCY_DATA>
  <CCY_DATA>
    <ORIG_CCY>USD</ORIG_CCY>
    <SETTLED_CCY>GBP</SETTLED_CCY>
    <EFFECTIVE_FROM>07 October 2003
    </EFFECTIVE_FROM>
    <ROE>1.6674</ROE>
    <EFFECTIVE_TO>31 December 2999
    </EFFECTIVE_TO>
  </CCY_DATA>
</CCY>

14:00:00,279 INFO  [example.db.SybaseMessaging] \
   === SybaseMessaging.updateData()
14:00:00,279 INFO  [STDOUT] \
   Hibernate: select iccy0_.ccy_id as x0_0_ \
   from IProducerCcy iccy0_ \
   where (iccy0_.send_status<>'S' )
14:00:00,289 INFO  [example.db.DBMessaging] \
   === DBMessaging.endTransaction() : Commit 
14:00:00,289 INFO  [STDOUT] \
   Hibernate: update IProducerCcy set orig_ccy=?,\
   settled_ccy=?, effective_from_date=?, \
   rate_of_exchange=?, effective_to_date=?, \
   send_status=?, send_date=? where ccy_id=?
14:00:00,299 INFO  [example.db.DBMessaging] \
   === DBMessaging.endSession()

Conclusion

This article was about how to use JBoss, Quartz, Hibernate, Castor, and WebSphere MQ to build a simple XML messaging system. Please consult the forums, Wikis, tutorials, docs, etc. in the Reference section below if you want to find out more about the components used.

Reference

Benoit Aumars Benoit Aumars has 14 years' experience in IT, specializing in Java and J2EE. His major interests include design patterns, XML-related technologies, EAI, web services, and SOA. He is currently working with Jardine Lloyd Thompson in London.


Return to ONJava.com.