So far we have consumed Services from a JSF page. It is however possible to consume them by means of other protocols. Transformation represents a change to the format and/or representation of a message's content.  The representation of a message is simply the Java contract (e.g. java.lang.String, org.example.MyFancyObject) used to access the underlying content.  The format of a message refers to the actual structure of the data itself.  Examples of data formats include XML, JSON, CSV, and EDI.


Transformers can be applied to a Java class using the org.switchyard.annotations.Transformer annotation which defines an incoming channel (from parameter) and an outgoing channel (to parameter).

 


package com.sample;

import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.stream.StreamSource;

import org.switchyard.annotations.Transformer;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import java.io.StringReader;

public class Transformers {
    // Transforms the incoming XML message to Calculator
    @Transformer(from = "{urn:switchyard-quickstart-demo:math:1.0}addition")
    public Calculator transform(Element from) {
        Calculator calc = new Calculator();

        calc.setNumber1(Integer.parseInt(getElementValue(from, "number1")));
        calc.setNumber2(Integer.parseInt(getElementValue(from, "number2")));
       
        return calc;
    }
    // Transforms the Result class into an XML response
    @Transformer(to = "{urn:switchyard-quickstart-demo:math:1.0}additionResponse")
    public Element transform(Result result) {
        StringBuffer ackXml = new StringBuffer()
            .append("<math:additionResponse xmlns:orders=\"urn:switchyard-quickstart-demo:math:1.0\">")
            .append("<Result>")
            .append("<total>" + result.getTotal() + "</total>")
            .append("</Result>")
            .append("</math:additionResponse>");

        return toElement(ackXml.toString());
    }


    private String getElementValue(Element parent, String elementName) {
        String value = null;
        NodeList nodes = parent.getElementsByTagName(elementName);
        if (nodes.getLength() > 0) {
            value = nodes.item(0).getChildNodes().item(0).getNodeValue();
        }
        return value;
    }

    private Element toElement(String xml) {
        DOMResult dom = new DOMResult();
        try {
            TransformerFactory.newInstance().newTransformer().transform(
                    new StreamSource(new StringReader(xml)), dom);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return ((Document)dom.getNode()).getDocumentElement();
    }
}

The "to" parameter can be omitted is the outgoing channel is a concrete java type. Conversely, you can omit the "from" if the incoming channel is a concrete Java type

The public Calculator transform(Element from) method will transform from a DOM element to a Calculator instance.

jboss soa switchyard tutorial esb
The public Element transform(Result result) converts from a Result java class to an XML element.
jboss soa esb switchyard
Since transformations occur between named types (i.e. from type A, to type B), it's important to understand how the type names are derived.  The type of the message is determined based on the service contract, which can be WSDL or Java.

In this example, the message name is determined based on the fully-qualified element name of a WSDL message.  Take the following WSDL definition (we have used wsprovide tool in JBOSS_HOME/bin to generate the WSDL see this link):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions 
    targetNamespace="urn:switchyard-quickstart-demo:math:1.0" 
    xmlns="http://schemas.xmlsoap.org/wsdl/" 
    xmlns:tns="urn:switchyard-quickstart-demo:math:1.0"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
    
  <types>
    <xsd:schema 
        targetNamespace="urn:switchyard-quickstart-demo:math:1.0" 
        xmlns:tns="urn:switchyard-quickstart-demo:math:1.0" 
        xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <xs:element name="addition" type="tns:additionType"/>
        <xs:element name="additionResponse" type="tns:additionResponseType"/>
        <xs:element name="calculator" type="tns:calculatorType"/>
        <xs:element name="result" type="tns:resultType"/>
        <xs:complexType name="additionType">
            <xs:sequence>
                <xs:element name="calculator" type="tns:calculatorType"/>
            </xs:sequence>
        </xs:complexType>
        <xs:complexType name="additionResponseType">
            <xs:sequence>
                <xs:element name="result" type="tns:resultType"/>
            </xs:sequence>
        </xs:complexType>
        <xs:complexType name="calculatorType">
            <xs:sequence>
                <xs:element name="number1" type="xs:int"/>
                <xs:element name="number2" type="xs:int"/>
               
            </xs:sequence>
        </xs:complexType>
        <xs:complexType name="resultType">
            <xs:sequence>
                <xs:element name="total" type="xs:int"/>
                 
            </xs:sequence>
        </xs:complexType>
    </xsd:schema>
  </types>
  
  <message name="addition">
    <part name="parameters" element="tns:addition"/>
  </message>
  <message name="additionResponse">
    <part name="parameters" element="tns:additionResponse"/>
  </message>
  
  <portType name="MathService">
    <operation name="addition">
      <input message="tns:addition"/>
      <output message="tns:additionResponse"/>
    </operation>
  </portType>
  
  <binding name="MathServiceBinding" type="tns:MathService">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
    <operation name="addition">
      <soap:operation soapAction="urn:switchyard-quickstart-demo:math:1.0"/>
      <input>
        <soap:body use="literal"/>
      </input>
      <output>
        <soap:body use="literal"/>
      </output>
    </operation>
  </binding>
  
  <service name="MathService">
    <port name="MathServicePort" binding="tns:MathServiceBinding">
      <soap:address location="http://localhost:18001/test"/>
    </port>
  </service>
</definitions>

Finally, you need to declare your Web service SOAP binding in your switchyard.xml file and the Transformers which will be used to convert the messages from one channel to another:
<?xml version="1.0" encoding="UTF-8"?>
<switchyard xmlns="urn:switchyard-config:switchyard:1.0" name="math" targetNamespace="urn:switchyard-quickstart-demo:math:0.1.0">
    <composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" name="math" targetNamespace="urn:switchyard-quickstart-demo:math:0.1.0">
        <service name="MathService" promote="MathService">
            <binding.soap xmlns="urn:switchyard-component-soap:config:1.0">
                <wsdl>wsdl/MathService.wsdl</wsdl>
                <socketAddr>:18001</socketAddr>
                <contextPath>calculator</contextPath>
            </binding.soap>  
        </service>
         
        <component name="MathService">
            <implementation.bean xmlns="urn:switchyard-component-bean:config:1.0" class="com.sample.MathServiceBean"/>
            <service name="MathService">
                <interface.java interface="com.sample.MathService"/>
            </service>
            
        </component>
    </composite>
    <transforms>
        <transform.java xmlns="urn:switchyard-config:transform:1.0" class="com.sample.Transformers" from="{urn:switchyard-quickstart-demo:math:1.0}addition" to="java:com.sample.Calculator"/>
        <transform.java xmlns="urn:switchyard-config:transform:1.0" class="com.sample.Transformers" from="java:com.sample.Result" to="{urn:switchyard-quickstart-demo:math:1.0}additionResponse"/>
    </transforms>
</switchyard>

Fine, now deploy your Web service. From the server logs, you will see that your Web service has been published at the socket address defined in your switchyard.xml file:

 

21:59:21,727 INFO  [org.switchyard.component.soap.InboundHandler] (MSC service thread 1-7) Publishing WebService at http://127.0.0.1:18001/calculator/MathService

 

Now you can use any SOAP Web service client to test your Web service against the WSDL which is reachable at http://127.0.0.1:18001/calculator/MathService?wsdl
Here's the SOAP outgoing message:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:switchyard-quickstart-demo:math:1.0">
   <soapenv:Header/>
   <soapenv:Body>
      <urn:addition>
         <calculator>
            <number1>5</number1>
            <number2>4</number2>
         </calculator>
      </urn:addition>
   </soapenv:Body>
</soapenv:Envelope>

And this is the returning SOAP message:

   <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
      <math:additionResponse xmlns:math="urn:switchyard-quickstart-demo:math:1.0">
         <Result>
            <total>9</total>
         </Result>
      </math:additionResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

In the next tutorial we will show how to use an Eclipse plugin (SOAP Ui) to invoke and test Web services. Stay tuned !

0
0
0
s2smodern