JBoss ESB Webservice Producer

User Rating: 0 / 5

Star InactiveStar InactiveStar InactiveStar InactiveStar Inactive
 

Important note: JBoss ESB is an archived project and its latest release dates back to Mar 2013. The replacement technology for it is JBoss Fuse which is an open source enterprise integration platform and service bus. You can find here a quickstart tutorial about JBoss Fuse.

The SOAPProcessor action, formerly known as "JBossWSAdapter", allows you to expose JBossWS 2.x and higher Webservice Endpoints through listeners running on the ESB (“SOAP onto the bus”).

A classic JBossESB usecase is one where the ESB is used to expose a Webservice interface for an existing Java based Service that doesn't already expose a Webservice interface. This means that these Services are invocable over any transport channel supported by the ESB (http, ftp, jms etc).
In order to achieve this, ESB defines a "wrapper webservice" that maps calls to the target Service.

Let's see in practice how to use the SOAPProcessor action. If you have downloaded the ESB service bus
move to the folder "samples\quickstarts\webservice_producer". There you can see one example of a WebService Producer.

Let's take a look at the jboss-esb.xml configuration file

<jbossesb
        xmlns="http://anonsvn.labs.jboss.com/labs/jbossesb/trunk/product/etc/schemas/xml/jbossesb-1.0.1.xsd"
        parameterReloadSecs="5">

    <providers>
        <jms-provider name="JBossMQ" connection-factory="ConnectionFactory">
            <jms-bus busid="quickstartGwChannel">
                <jms-message-filter dest-type="QUEUE" dest-name="queue/quickstart_webservice_producer_gw"/>
            </jms-bus>
            <jms-bus busid="quickstartEsbChannel">
                <jms-message-filter dest-type="QUEUE" dest-name="queue/quickstart_webservice_producer_esb"/>
            </jms-bus>
        </jms-provider>

        <jbr-provider name="JBR-Http" protocol="http" host="localhost">
            <jbr-bus busid="Http-1" port="8765" />
        </jbr-provider>

        <jbr-provider name="JBR-Socket" protocol="socket" host="localhost">
            <jbr-bus busid="Socket-1" port="8888" />
        </jbr-provider>

    </providers>

    <services>

        <service category="MyServiceCategory" name="MyWSProducerService" description="WS Frontend speaks natively to the ESB">

            <listeners>
                <jms-listener name="JMS-Gateway" busidref="quickstartGwChannel" is-gateway="true"/>
                <jbr-listener name="Http-Gateway" busidref="Http-1" is-gateway="true"/>
                <jbr-listener name="Socket-Gateway" busidref="Socket-1" is-gateway="true"/>

                <jms-listener name="JMS-ESBListener" busidref="quickstartEsbChannel"/>
            </listeners>
            <actions>
                <action name="print-before" class="org.jboss.soa.esb.actions.SystemPrintln">
                    <property name="message"
                              value="[Quickstart_webservice_producer] BEFORE invoking jbossws endpoint"/>
                </action>
                <action name="JBossWSAdapter" class="org.jboss.soa.esb.actions.soap.SOAPProcessor">
                    <property name="jbossws-endpoint" value="GoodbyeWorldWS"/>
                </action>
                <action name="print-after" class="org.jboss.soa.esb.actions.SystemPrintln">
                    <property name="message"
                              value="[Quickstart_webservice_producer] AFTER invoking jbossws endpoint"/>
                </action>
        <action name="testStore" class="org.jboss.soa.esb.actions.TestMessageStore"/>    
            </actions>
        </service>

    </services>

</jbossesb>

The first thing to notice is that JBoss ESB uses JBoss remoting interfaces as provider for http and socket transport. We'll explain later a bit more about jBoss remoting. In order to receive http/socket requests it's necessary to install a listener for this interfaces. This is achieved with the  <jbr-listener>

JBoss ESB

Picture 1: JBoss ESB exposing WebServices over http,socket,jms protocols

Said that, the action needed to invoke the webservice is very straightforward.  The action requires only one mandatory property value, which is the "jbossws-endpoint" property.  This property names the JBossWS endpoint that the SOAPProcessor is exposing (invoking).

<action name="JBossWSAdapter" class="org.jboss.soa.esb.actions.soap.SOAPProcessor">
      <property name="jbossws-endpoint" value="GoodbyeWorldWS"/>
 </action>


Notice : There's one optional property "rewrite-endpoint-url" which is not used in this sample. This property is there to support load balancing on HTTP endpoints, in which case the Webservice endpoint container will have been configured to set the HTTP(S) endpoint address in the WSDL to that of the Load Balancer.

The Web Service endpoint is deployed in the .esb archive as web application. It's made up of only one class and exposed 3 WebMethods:

@WebService(name = "GoodbyeWorldWS", targetNamespace="http://webservice_producer/goodbyeworld")
public class GoodbyeWorldWS {

    @WebMethod
    public String sayGoodbye(@WebParam(name="message") String message) {

        Message esbMessage = SOAPProcessor.getMessage();
        if(esbMessage != null) {
            System.out.println("**** SOAPRequest perhaps mediated by ESB:\n" + esbMessage.getBody().get());
        }
        System.out.println("Web Service Parameter - message=" + message);
        return "... Ah Goodbye then!!!! - " + message;
    }

    @WebMethod
    public String sayAdios(String message) {
        Message esbMessage = SOAPProcessor.getMessage();
        if(esbMessage != null) {
            System.out.println("**** SOAPRequest perhaps mediated by ESB:\n" + esbMessage.getBody().get());
        }
        System.out.println("Web Service Parameter - message=" + message);
        return "... Adios Amigo!!!! - " + message;
    }
    
    @WebMethod
    @Oneway
    public void sayGoodbyeWithoutResponse(@WebParam(name="message") String message) {

        Message esbMessage = SOAPProcessor.getMessage();
        if(esbMessage != null) {
            System.out.println("**** SOAPRequest perhaps mediated by ESB:\n" + esbMessage.getBody().get());
        }
        System.out.println("Web Service Parameter - message=" + message);
    }


ok time to deploy your .esb archive.

$ ant deploy

 

11:40:56,546 INFO  [TomcatDeployer] deploy, ctxPath=/Quickstart_webservice_producer, warUrl=.../tmp/deploy/tmp51717Quickstart_webservice_producer.esb-contents/Quickstart_webservice_producer-exp.war/

11:40:58,515 INFO  [WSDLFilePublisher] WSDL published to: file:/D:/jbossesb-server-4.4.GA/server/default/data/wsdl/Quickstart_webservice_producer.esb/Quickstart
_webservice_producer.war/GoodbyeWorldWSService51718.wsdl

 

If everything was successful .esb archive is now available and the wsdl archive was generated.

Ok now the webservice is deployed but how the client interface knows which protocol can be used to interact with the WebServices ? this problem is solved by the ESB exposing a contract for the webservice.

This application lists URLs that can be used by your Webservice Client (e.g. soapUI) for accessing a Service's WSDL, enabling WSDL based invocation of the Service through an ESB Endpoint.

The SOAPProcessor Action publishes contract information by being annotated with the org.jboss.internal.soa.esb.publish.Publish annotation as follows :

@Publish(WebserviceContractPublisher.class)
public class SOAPProcessor extends AbstractActionPipelineProcessor {
...
}

 

 

If you want to inspect the Contract for the Webservice take a look at the Contract console at
http://localhost:8080/contract/


jboss esb web services

 Picture 2: JBoss ESB Contracts console showing the available protocols for WebService endpoints
Connecting to your webservice

 

Last piece of the puzzle is the client which connects to the WebService. We'll skip the JMS sendMethod (which is a plain JMS client ) rather it's interesting to note how to connect to your remote listener:

 private void sendMessageToJBRListener(String protocol, int port, String message) throws Throwable {
        String locatorURI = protocol + "://localhost:" + port;
        InvokerLocator locator = new InvokerLocator(locatorURI);
        System.out.println("Calling JBoss Remoting Listener using locator URI: " + locatorURI);

        Client remotingClient = null;
        try {
            remotingClient = new Client(locator);
            remotingClient.connect();

            // Deliver the message to the listener...
            Object response = remotingClient.invoke(message);
            System.out.println("JBR Class: " + response.getClass().getName());
            System.out.println("Response from JBoss Remoting Listener '" + locatorURI + "' was '" + response + "'.");
        } finally {
            if(remotingClient != null) {
                remotingClient.disconnect();
            }
        }
    }

This method used JBoss remoting framework : What is it about ? JBoss remoting is a core framework that provides remote services like remoting JMX MBeans, remoting EJBs, and so on.  It supports an invocation model much more versatile then RMI or old-styled web services. There is no need to generate and compile a client-side agent for each service. As a result, JBoss Remoting provides the basis for more complex and heavyweight remoting frameworks.

 

JBoss Remoting defines the org.jboss.remoting.InvokerLocator class : this is the object that identifies the location of our service, as well as describing what transport protocol to use.

As you can see from the method sendMessageToJBRListener, the code is independent from the protocol: you simply feed the protocol : so for example if you use http, you'll use the JBR protocol "http://localhost:8765" , while for socket you'll use JBR protocol "socket://localhost:8888"

This is all you need in order to create a client that can be used to locate and connect to a remote service.

{fcomment}


Advertisement