このコンテンツは選択した言語では利用できません。
Chapter 11. Transformer
11.1. What is a Transformer
It is not possible for the message providers to know what format of message is expected by every consumer. Therefore Transformers are used to enable the loose-coupling of message providers and message consumers. Transformers convert message content to various formats, thereby playing an important role in connecting service consumers and providers.
11.2. Transformation in SwitchYard
Transformation represents a change to the format or representation of a message's content. The representation of a message is the Java contract used to access the underlying content. For example,
java.lang.String
and org.example.MyFancyObject
. The format of a message refers to the actual structure of the data itself. Examples of data formats include XML, JSON, CSV, and EDI. Here is an example of message content in XML format:
<MyBook> <Chapter1> <Chapter2> </MyBook>
You can also represent XML in Java as a String. For example:
String content = "<MyBook>...";
Transformation plays an important role in connecting service consumers and providers, as the format and representation of message content can be quite different between the two. For example, a SOAP gateway binding is likely use a different representation and format for messages than a service offered by a Java Bean. In order to route services from the SOAP gateway to the Bean providing the service, the format and representation of the SOAP message needs to change. Implementing the transformation logic directly in the consumer or provider pollutes the service logic and can lead to tight coupling. SwitchYard allows you to declare the transformation logic outside the service logic and inject into the mediation layer at runtime.
11.3. Adding Transformation to a SwitchYard Application
You can specify transformation of message content in the descriptor of your SwitchYard application (
switchyard.xml
). The qualified name of the type being transformed from as well as the type being transformed to are defined along with the transformer implementation. This allows transformation to be a declarative aspect of a SwitchYard application, as the runtime automatically registers and executes transformers in the course of a message exchange. Here is an example of message content transformation:
<transforms> <transform.java bean="MyTransformerBean" from="{urn:switchyard-quickstart-demo:orders:1.0}submitOrder" to="java:org.switchyard.quickstarts.demos.orders.Order"/> </transforms>
11.4. Chaining Transformers
JBoss Fuse Service Works 6.0 allows you to chain transformers. Say you have a transformer that transforms from A to B and another that transforms from B to C. If you then have an invocation where the consumer is using type A and the provider is using type C, then the runtime will invoke the A->B and the B->C transformers to achieve A->C.
For example, for a SOAP message, you could define two transformers:
<transform:transform.java from="{http://web.service.com/}GetStatisticsResponse" to="{urn:web.service.com}StatisticsCData" bean="CDataReturn"/> <transform:transform.jaxb from="{urn:web.service.com}StatisticsCData" to="java:com.sample.model.Statistics" contextPath="com.sample.model"/>
The first transformer transforms the SOAP reply which contains the
GetStatisticsResponse
element into an intermediate object which is just the content of the return element (CDATA containing the element), implemented in Java as follows:
@Named("CDataReturn") public class CDataExtractor { @Transformer(from = "{http://web.service.com/}GetStatisticsResponse", to = "{urn:web.service.com}StatisticsCData") public String transform(Element from) { String value = null; NodeList nodes = from.getElementsByTagName("return"); if(nodes.getLength() > 0 ){ value = nodes.item(0).getChildNodes().item(0).getNodeValue(); } return value; } }
The second transformer then takes care of transforming from the element to the Statistics Java model using JAXB.
JBoss Fuse Service Works 6.0 knows, from the contracts on the reference definitions, that it needs to go from
{http://web.service.com/}GetStatisticsResponse
to java:com.sample.model.Statistics
and will automatically invoke both transformers to make that happen.
See Unable to transform from SOAP response with CDATA block to a POJO in FSW 6 for more information.
11.5. Adding a Transformer Using SwitchYard Editor
This section describes how to add a transformer to an application in the SwitchYard editor. The example in this section shows how to add a Smooks transformer.
- Select the main object (transform-smooks) in the SwitchYard editor.
Figure 11.1. Smooks Transformations in SwitchYard Editor
- Select the Transforms tab in the Properties view. The existing transformers are listed.
- Selectto add new transformers.
Figure 11.2. List of Transformers Under Properties View
Note
- Users are not able to add transformers unless they are required.
- If no transformers are visible in the properties page, try updating the Maven project configuration by right-clicking the project and selecting
.
11.6. Message Content Type Names
Since transformations occur between named types (for example, from type A to type B), it is 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.
- WSDLFor WSDL interfaces, the message name is determined based on the fully-qualified element name of a WSDL message. Here is an example of a WSDL definition:
<definitions xmlns:tns="urn:switchyard-quickstart:bean-service:1.0"> <message name="submitOrder"> <part name="parameters" element="tns:submitOrder"/> </message> <portType name="OrderService"> <operation name="submitOrder"> <input message="tns:submitOrder"/> </operation> </portType> </definitions>
This yields the following message type name based on the message element name defined in the WSDL:{urn:switchyard-quickstart:bean-service:1.0}submitOrder
- JavaFor Java interfaces, the message name consists of the full package name and the class name prefixed with "
java:
". Here is an example of a Java definition:package org.switchyard.example; public interface OrderService { void submitOrder(Order order); }
This yields the following message type name:java:org.switchyard.example.Order
You may override the default operation name generated for a Java interface. The @OperationTypes annotation provides this capability by allowing you to specify the input, output, and fault type names used for a Java service interface. For example, if you want to accept XML input content without any need for transformation to a Java object model, you can change theOrderService
interface as shown below:package org.switchyard.example; public interface OrderService { @OperationTypes(in = "{urn:switchyard-quickstart:bean-service:1.0}submitOrder") void submitOrder(String orderXML); }
This annotation can be useful if you want to maintain a tight control over the names used for message content.
11.7. Supported Transformations
11.7.1. Java
11.7.1.1. Java Transformer
You can create a Java-based transformer in SwitchYard using any of the following methods:
When using the @Transformer annotation, the SwitchYard maven plug-in automatically generates the <transform.java> definition and adds them to the
- Implement the
org.switchyard.transform.Transformer
interface and add a <transform.java> definition to yourswitchyard.xml
. - Annotate one or more methods on your Java class with @Transformer annotation.
switchyard.xml
packaged in your application. Here is an example of a Java class that produces the <transform.java> definition:
@Named("MyTransformerBean") public class MyTransformer { @Transformer(from = "{urn:switchyard-quickstart-demo:orders:1.0}submitOrder") public Order transform(Element from) { // handle transformation here } }Here, the
from
and to
elements of the @Transformer annotation are optional. You can use them to specify the qualified type name used during transformer registration. If not specified, the full class name of the method parameter is used as the from
type and the full class name of the return type is used as the to
type.
The CDI bean name specified by @Named annotation is used to resolve transformer class. If not specified, the class name of the transformer is used instead. Here is an example:
<transforms> <transform.java class="org.switchyard.quickstarts.demos.orders.MyTransformer" from="{urn:switchyard-quickstart-demo:orders:1.0}submitOrder" to="java:org.switchyard.quickstarts.demos.orders.Order"/> </transforms>
Note
The bean attribute and class attribute are mutually exclusive.
11.7.2. JAXB
11.7.2.1. JAXB Transformer
SwitchYard automatically detects and adds the JAXB Transformations for your application deployment. For example, if you develop a CDI Bean Service and use JAXB generated types in the Service Interface, you do not need to configure any of the transformations. SwitchYard automatically detects their availability for your application and automatically applies them at the appropriate time during service invocation.
The JAXB transformer allows you to perform Java to XML and XML to Java transformations using JAXB (XML marshalling and unmarshalling). The JAXB Transformer is similar to the JSON Transformer configuration. It also requires a
to
and from
configuration with one Java type and one QNamed XML type.
For example in the source file
ObjectFactory.java
, the factory methods represent the available marshallings/unmarshallings as shown below:
@XmlElementDecl(namespace = "http://com.acme/orders", name = "create") public JAXBElement<CreateOrder> createOrder(CreateOrder value) { return new JAXBElement<Order>(_CreateOrder_QNAME, CreateOrder.class, null, value); }Here, the @XmlElementDecl annotation implies that the XML QName associated with the
com.acme.orders.CreateOrder
type is "{http://com.acme/orders}create". This means that you can have the following SwitchYard JAXB Transformer configurations:
<transform.jaxb from="{http://com.acme/orders}create" to="java:com.acme.orders.CreateOrder" /> <transform.jaxb from="java:com.acme.orders.CreateOrder" to="{http://com.acme/orders}create" />
11.7.3. JSON
11.7.3.1. JSON Transformer
The JSON transformer provides a basic mapping facility between POJOs and JSON (JSON marshalling and unmarshalling). Just like the JAXB Transformer, specification of the transformer requires a
to
and from
specification with one Java type and one QNamed JSON type, depending on whether you are performing a Java to JSON or JSON to Java transformation.
Here is an example configuration of JSON to Java transformation:
<trfm:transform.json from="{urn:switchyard-quickstart:transform-json:1.0}order" to="java:org.switchyard.quickstarts.transform.json.Order"/>
Here is a sample configuration of Java to JSON transformation:
<trfm:transform.json from="java:org.switchyard.quickstarts.transform.json.Order" to="{urn:switchyard-quickstart:transform-json:1.0}order"/>
11.7.4. Smooks
11.7.4.1. Smooks Transformer
SwitchYard provides three distinct transformation models for Smooks:
- XML to Java : Based on a standard Smooks Java Binding configuration.
- Java to XML: Based on a standard Smooks Java Binding configuration.
- Smooks : This is a normal Smooks transformation in which you must define which Smooks filtering result is to be exported back to the SwitchYard Message as the transformation result.
You can declare a Smooks transformation by including a <transform.smooks> definition in your
switchyard.xml
. Here is an example:
<transform.smooks config="/smooks/OrderAck_XML.xml" from="java:org.switchyard.quickstarts.transform.smooks.OrderAck" to="{urn:switchyard-quickstart:transform-smooks:1.0}submitOrderResponse" type="JAVA2XML"/>The Smooks and XSLT translators require an external configuration file that tells the translator how to go about its actions. In the example above, the
config
attribute points to a Smooks resource containing the mapping definition. The type
attribute can be one of SMOOKS, XML2JAVA, or JAVA2XML.
For more information on Smooks and XSLT configuration files, see Red Hat JBoss Fuse Service Works Development Guide Volume 2: Smooks.
For more information on the elements that extend the abstract transform, see the
/docs/schema/soa/org/switchyard/transform/config/model/v1/transform_<latest_version>.xsd
.
11.7.5. XSLT
11.7.5.1. XSLT Transformer
You can perform transformations with the XSLT transformer using an XSLT. You can configure it by specifying the
to
and from
QNames, and the path to the XSLT. Here is an example of XSLT Transformer configuration:
<transform.xslt from="{http://acme/}A" to="{http://acme/}B" xsltFile="com/acme/xslt/A2B.xslt"/>