Friday, August 24, 2012

JBoss ESB http-gateway service

We can call an ESB service in different ways; It can be invoked via queue messages, HTTP requests, webservices, and so on... In this post we will work with the JBoss ESB and see how we can invoke a service with a HTTP POST request.

Versions used:
- JBoss AS 5.1.0.GA (Community version)
- JBoss ESB 4.11 (not the standalone one, the version which is deployed in the AS)

Let's see the example!


pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <groupId>ar.com.pabloExample</groupId>
 <artifactId>helloworld-jboss-esb</artifactId>
 <version>1.0-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>helloworld-jboss-esb</name>
 <url>http://maven.apache.org</url>

 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <jboss.home>/opt/jboss</jboss.home>
 </properties>

 <dependencies>

  <dependency>
   <groupId>org.jboss.soa.bpel.dependencies.esb</groupId>
   <artifactId>jbossesb-rosetta</artifactId>
   <version>4.11</version>
   <scope>system</scope>
   <systemPath>${jboss.home}/server/esb-default/deployers/esb.deployer/lib/jbossesb-rosetta.jar</systemPath>
  </dependency>
  
  <!-- For testing purposes -->

  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>4.8.2</version>
   <scope>test</scope>
  </dependency>

  <dependency>
   <groupId>commons-httpclient</groupId>
   <artifactId>commons-httpclient</artifactId>
   <version>3.1</version>
   <scope>test</scope>
  </dependency>
  
  <dependency>
   <groupId>log4j</groupId>
   <artifactId>log4j</artifactId>
   <version>1.2.17</version>
   <scope>test</scope>
  </dependency>

 </dependencies>

 <build>
  <finalName>helloworld-jboss-esb</finalName>

  <plugins>

   <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jboss-packaging-maven-plugin</artifactId>
    <version>2.2</version>
    <configuration>
     <archiveName>helloworld-jboss-esb</archiveName>
    </configuration>
    <executions>
     <execution>
      <id>build-esb</id>
      <goals>
       <goal>esb</goal>
      </goals>
     </execution>
    </executions>
   </plugin>

   <!-- mvn jboss:hard-deploy -->
   <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jboss-maven-plugin</artifactId>
    <version>1.5.0</version>
    <configuration>
     <jbossHome>/opt/jboss</jbossHome>
     <serverName>esb-default</serverName>
     <fileName>target/helloworld-jboss-esb.esb</fileName>
    </configuration>
   </plugin>

   <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
     <source>1.6</source>
     <target>1.6</target>
    </configuration>
   </plugin>

  </plugins>
 </build>

</project>

The jboss-maven-plugin is just a plugin to ease the process of copying the esb file generated to the jboss server. Of course this is not mandatory :)

The jboss-packaging-maven-plugin is the plugin responsible for creating the ESB file that will be deployed in the server.


jboss-esb.xml
<jbossesb
 xmlns="http://anonsvn.labs.jboss.com/labs/jbossesb/trunk/product/etc/schemas/xml/jbossesb-1.2.0.xsd"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://anonsvn.labs.jboss.com/labs/jbossesb/trunk/product/etc/schemas/xml/jbossesb-1.0.1.xsd http://anonsvn.jboss.org/repos/labs/labs/jbossesb/trunk/product/etc/schemas/xml/jbossesb-1.2.0.xsd"
 parameterReloadSecs="5">
 
 <services>

  <service name="helloWorldService" category="helloWorldCategory" description="Hello World" invmScope="GLOBAL">
  
   <listeners>
    <http-gateway name="http-gateway" payloadAs="STRING"/>
   </listeners>
  
   <actions mep="RequestResponse">

    <!-- This action prints the content of the message -->
    <action name="action1" class="org.jboss.soa.esb.actions.SystemPrintln">
     <property name="printfull" value="false" />
    </action>
    
    <action name="action2" class="ar.com.pabloExample.service.MessageCustomAction" process="process" />

    <!-- This action logs a user text and the service name -->
    <action name="action3" class="org.jboss.soa.esb.actions.ServiceLoggerAction">
     <property name="text" value="Message arrived" />
     <property name="log-payload-location" value="true" />
    </action>

   </actions>
  </service>
  
 </services>

</jbossesb>

In jboss-esb.xml we define a service with 3 actions:
"action1" & "action3" : they do some logging
"action2" : takes the "name" query parameter from the URL and creates the "hello <query parameter>" string which is put in the ESB message body

A listener is defined too. The HTTP listener will trigger the service whenever a POST request is make to a special URL (see the test section to see which is that URL).


MessageCustomAction.java
public class MessageCustomAction extends AbstractActionPipelineProcessor {

 public MessageCustomAction(final ConfigTree config) {
  // extract configuration
 }

 @Override
 public Message process(Message message) throws ActionProcessingException {

        HttpRequest req = HttpRequest.getRequest(message);
        Map<String, String[]> params = req.getQueryParams();
        
        String name = params.get("name")[0];
        
        message.getBody().add("Hello " + name);
  
        return message;
 }

}

Here we define the way to process the ESB message, we interpret it as a HTTP request and retrieve the "name" query parameter.


Let's test the ESB service!



HttpRequestServiceTest.java
public class HttpRequestServiceTest {
 
 private static Logger logger = Logger.getLogger(HttpRequestServiceTest.class);
 
 @Test
 public void httpRequestServiceTest() throws HttpException, IOException {
  
 HttpClient client = new HttpClient();
        PostMethod post = new PostMethod("http://localhost:8080/helloworld-jboss-esb/http/helloWorldCategory/helloWorldService");
        post.setQueryString("?name=pablito");
        client.executeMethod(post);
        
        String result = post.getResponseBodyAsString();
        post.releaseConnection();

        logger.info("Service returned: " + result);
 }
}

In this test we simply do a HTTP post to the following URL:
http://localhost:8080/helloworld-jboss-esb/http/helloWorldCategory/helloWorldService

Note that using the default http-gateway the pattern to use would be like this:
http://<server>:<port>/<deployed esb file>/http/<category name>/<service name>


To run this test, create the ESB file and deploy it in the server:
  1. Set the jboss.home property in the pom.xml
  2. mvn clean package -Dmaven.test.skip=true jboss:hard-deploy
Now run the test with mvn test and you're done!


Download the example:


https://subversion.assembla.com/svn/pablo-examples/helloworld-jboss-esb

2 comments:

  1. Hi Nice Blog Thanks For Sharing Post.

    The <.esbname> token being the name of the .esb deployment, without the “.esb” extension. Note also the “http” token in the address. This is a hardcoded namespace prefix used for all endpoints.

    JBoss Development


    Thanks.

    ReplyDelete
  2. Hi, that's correct, thanks for clarifying the example!

    ReplyDelete