Thursday, 16 June 2011


I had quite a lot of trouble getting all these frameworks to play well together in a way that I was happy with and would allow me to move forward. I did find this article by Quinton Anderson which is incredibly useful but it didn't work for me and I also wanted to make use of Spring 3 annotations more.

My requirements were to use the JBoss ESB to generate a web service, unmarshal the XML, then feed into a custom Spring action ready for persisting. Obviously the ESB itself can do the persisting but as I'm going to be building a Spring application I want to ensure I can get the data into Spring as in the future we'll be building business logic in there. Just to complicate things a little further and again for future scalability the message itself would be sent over JMS once received into the bus.

The appropriate snippets of my jboss-esb.xml as as follows :-
 <?xml version="1.0"?> <jbossesb parameterReloadSecs="5" xmlns=" xml/jbossesb-1.3.0.xsd" xmlns:xsi="" xsi:schemaLocation="">  
 <jms-provider connection-factory="ConnectionFactory" name="ReceiveMarshalledDatex2Message">  
   <jms-bus busid="marshalledDatex2Channel">  
   <jms-message-filter dest-name="queue/SimpleJMSRequest" dest-type="QUEUE"/>  
 <service category="WsServiceCategory" description="I receive messages and send over JMS" invmScope="GLOBAL" name="WsService">  
   <property name="maxThreads" value="100"/>  
   <actions inXsd="/request.xsd" mep="RequestResponse" outXsd="/response.xsd" responseLocation="RESPONSE" webservice="true">  
  <action class="org.jboss.soa.esb.actions.Notifier" name="NotifyAction2">  
    <property name="okMethod" value="notifyOK"/>  
    <property name="destinations">  
   <NotificationList type="ok">  
     <target class="NotifyQueues">  
     <queue jndiName="queue/SimpleJMSRequest"/>  
  <service category="Datex2_Service"  
   description="Processes a unmarshalled Datex2 Message" invmScope="GLOBAL"n ame="ProcessDatex2MarshalledService">  
   <property name="maxThreads" value="100"/>  
   <jms-listener busidref="marshalledDatex2Channel" is-gateway="true" maxThreads="100" name="ListenDatex2Marshall"/>  
  <action class="com.thales.esbtest.ConvertDatex2ActionWs" name="UnmarshalXML"/>  
 <action class="com.thales.esbtest.MyTestSpringAction" name="MySpringAction">  
    <property name="springContextXml" value="/lib/applicationContext.xml"/>  

For the JMS you'll need to add a file (jbm-queue-service.xml) into your ESB archive to declare the JMS queue :
 <?xml version="1.0" encoding="UTF-8"?>  
  <mbean code="org.jboss.jms.server.destination.QueueService"  
   <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>  

In addition, I found I needed a deployment.xml file to ensure the queue is created before the ESB is processed :
 <?xml version="1.0" encoding="UTF-8"?>  

My unmarshall action looks like 
 public class ConvertDatex2ActionWs {  
   private JAXBContext jaxbContext;  
   public ConvertDatex2ActionWs() {  
     try {  
       jaxbContext = JAXBContext.newInstance("eu.datex2.schema._2_0rc2._2_0");  
     } catch (JAXBException e) {  
       // TODO Auto-generated catch block  
   public Object process(Message message) throws ActionProcessingException {  
     DeliverDatex2Request deliverDatex2Request = null;  
     try {  
       Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();  
       deliverDatex2Request = (DeliverDatex2Request) unmarshaller.unmarshal(new StreamSource(new StringReader(  
           (String) message.getBody().get())));  
     } catch (JAXBException e) {  
       // TODO Auto-generated catch block  
     if (deliverDatex2Request == null)  
       return null;  
     message.getBody().add("unmarshalled", deliverDatex2Request.getDatex2Message());  
     return message;  
   public Object processSuccess(Message message) {  
   public void manualRollback(Message message, Throwable theError) {  
     System.out.println("on exception called");  

My custom Spring Action :
 public class MyTestSpringAction extends AbstractSpringAction {  
   public void process(final Message message) throws ActionProcessingException, ActionLifecycleException,  
       BeansException {  
     AutService service = (AutService) getBeanFactory().getBean("AutService");  

My AutService implementation :
 public class AutServiceImpl implements AutService, InitializingBean {  
  private LocationDao locationDao;  
  public void write(...) {  
     Location entity = new Location();  

My implementation DAO class :
 public class JpaLocationDao implements LocationDao {  
   private EntityManager entityManager;  
   public void setEntityManager(EntityManager em) {  
     this.entityManager = em;  
   public void save(Location location) {  

Now importantly! my persistence.xml :
 <persistence xmlns=""  
    <persistence-unit name="AutJPA" transaction-type="JTA">  
          <!-- <jta-data-source>java:/XAOracleDS</jta-data-source> -->  
      <!-- Auto-detect entity classes -->  
    <property name="hibernate.archive.autodetection" value="class, hbm"/>  
     <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/>  
         <property name="" value="persistence-units/AutJPA"/>  
       <property name="hibernate.ejb.cfgfile" value="/lib/hibernate.cfg.xml" />  

My applicationContext.xml
 <context:load-time-weaver weaver-class="org.jboss.instrument.classloading.JBoss5LoadTimeWeaver"/>  
     <!-- tell spring to use annotation based configurations -->  
     <!-- tell spring where to find the beans -->  
     <context:annotation-config />  
     <context:component-scan base-package="com.thales.esbtest"/>  
     <jee:jndi-lookup id="myEmf" jndi-name="persistence-units/AutJPA" />  
     <tx:annotation-driven mode="proxy" transaction-manager="txManager" />  
         class="" />  
     <!-- Configure Transaction Support - Access the JTA transaction manager -->  
     <bean id="txManager"  
         <property name="transactionManagerName" value="java:/TransactionManager" />  
         <property name="userTransactionName" value="UserTransaction" />  
     <!-- Use Spring AOP capabilities to manage transactions -->  
         <aop:pointcut id="accountTransactions"  
             expression="execution(* com.thales.esbtest.MyTestSpringAction.*(..))" />  
         <aop:advisor pointcut-ref="accountTransactions"  
             advice-ref="txAdvice" />  
     <tx:advice id="txAdvice" transaction-manager="txManager">  
             <tx:method name="process" propagation="REQUIRED" />  
             <tx:method name="*" propagation="SUPPORTS" read-only="true" />  

Finally my hibernate.cfg.xml 
 <?xml version='1.0' encoding='UTF-8'?>  
 <!DOCTYPE hibernate-configuration PUBLIC  
  "-//Hibernate/Hibernate Configuration DTD 3.0//EN"  
          <property name="">create</property>  
         <property name="show_sql">true</property>  
         <property name="dialect">org.hibernatespatial.postgis.PostgisDialect</property>  
         <!-- <property name="dialect"></property> -->  
         <property name="current_session_context_class">thread</property>  
         <property name="hibernate.session_factory_name">SessionFactory</property>  
         <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>  
         <property name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</property>  
         <property name="hibernate.validator.apply_to_ddl">false</property>  
         <property name="hibernate.validator.autoregister_listeners">false</property>  
         <mapping class="com.thales.esbtest.Location" />  

There's a few more enhancements needed. I still need to specify my entity classes in the hibernate.cfg.xml which I'd like to eliminate and have these be found automatically. Some other gotchas that I had to solve were :

1) You'll need to install the Snowdrop utility Without this you'll get an I/O failure during classpath scanning; nested exception is error in opening zip file
I took the 3 Jar files and installed them in the JBoss lib directory.

2) You'll need to install the springsource aspectj weaver and tools libraries from otherwise you'll get a java.lang.NoClassDefFoundError: org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException

3) Finally I was getting security exception and I finally tracked this down to where you need to replace cglib

I hope someone finds this useful as you can spend a long while scratching around trying to pull all this together. In a future blog I will show how easy this was using Gradle and Eclipse.

The versions I was using :
JBoss 5.1.0.GA (Enterprise Version)
Spring 3.0.5
Hibernate 3.3.2.GA (comes with JBoss 5.1.0.GA)

No comments:

Post a Comment