Creating reusable JBoss ESB archives

When building integrations with JBoss ESB you naturally need to interact with other systems via notification gateways other than messaging queues. It could be that you need to enrich data from a WS-SOAP service or just put data into a file in a specific directory. These addresses and location often need to be different depending on which environment you are running in.

For example if you run in system test you probably do not want to write the file to the directory where the production system you integrate with looks for incoming files. Or if you have a very general service pipeline, that you deploy at multiple customers, you want to be able to change the WS-SOAP endpoint for each customer.

Decide at package time

One solution I often see to this problem is to use maven or ant to do package time filtering of the jboss-esb.xml file. However the trade-off with this solution is that you will need to repackage your ESB archive for each environment. You will also need to define a profile for each environment you want to package for.

Decide at runtime

A far more compelling idea is to be able to set these in runtime. And luckily JBoss perform system property replacement on the jboss-esb.xml files. So you could in your jboss-esb.xml file simply specify ${outbox} and then when starting JBoss add -Doutbox=/srv/ftp/outbox to the command line. The simplest way to do this is to add a new line in the run.conf file that reads something like this.

JAVA_OPTS="$JAVA_OPTS -Doutbox=/srv/ftp/outbox"

On deployment JBoss will then replace all occurrences of ${outbox} with /srv/ftp/outbox in your services. However there is in my opinion two cavatees with this approach.

First the system properties are global which means that you need to make sure that you do not use a property name which could be used in another service (unless they actually need to have the same value). The second is that the command line of the running process can very quickly increase in length and there is actually a limit on how long a command line is allowed to be.

The first issue can easily be, if not solved then mitigated. Simply add your package name in the system property. So instead of using the generic term outbox you can use a more specific term com.ullgren.pontus.filetransferservice.outbox. This way there is a smaller risk that another service uses the same system property and you avoid a conflict.

The second issue can be solved by deploying SystemPropertiesService. Create your own service xml file (something like myfiletransfer-property-service.xml) and package it in your ESB archive.

        <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE server>
         
        <server>
         <mbean code="org.jboss.varia.property.SystemPropertiesService"
            name="jboss:type=Service,name=MyFiletransferProperties">
         <attribute name="URLList">
            conf/myservice.properties
         </attribute>
         </mbean>
        </server>

You will need to make sure that this SystemPropertiesService is loaded before your ESB service. To do this add a file called deployment.xml into the META-INF directory in your ESB archive.

<jbossesb-deployment>
  <depends>jboss.esb:deployment=soap.esb</depends>
  <depends>jboss:type=Service,name=MyFiletransferProperties</depends>
</jbossesb-deployment>

Then you can easily edit the properties file conf/myservice.properties and add the properties you want to load.

com.ullgren.pontus.filetransferservice.inbox=/srv/ftp/inbox
com.ullgren.pontus.filetransferservice.outbox=/srv/ftp/outbox

This properties files needs to be maintained for each environment you want to deploy your service in.

Example code

Example code used when creating this blog post is available on github.

Credits

Thanks to my co-worker Johan Carlsson for showing me the technique of using a SystemPropertiesService with an external properties file.