Major progress on Gradle port
Complete: -------- - src/* documentation resources moved to 'docs' subproject - docbook sources upgraded to Docbook 5 - formatted all docbook sources to strip tab characters and eliminate trailing whitespace - all projects compile and test successfully - all artifacts upload successfully to s3, static.sf.org, etc. Remaining: --------- - documentation L&F needs work. CSS, images, and highlighting aren't hooked up properly - spring-integration-jdbc codegen bits in Maven POM need to be transcribed into gradle - dependencies that were optional or provided scope in maven are currently 'compile' scope in Gradle. Need to figure out support in Gradle to fix this. - run through Eclipse classpath and project generation scenarios - delete all Maven artifacts
This commit is contained in:
183
docs/src/reference/docbook/transformer.xml
Normal file
183
docs/src/reference/docbook/transformer.xml
Normal file
@@ -0,0 +1,183 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="transformer"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>Transformer</title>
|
||||
|
||||
<section id="transformer-introduction">
|
||||
<title>Introduction</title>
|
||||
<para>
|
||||
Message Transformers play a very important role in enabling the loose-coupling of Message Producers and Message
|
||||
Consumers. Rather than requiring every Message-producing component to know what type is expected by the next
|
||||
consumer, Transformers can be added between those components. Generic transformers, such as one that converts a
|
||||
String to an XML Document, are also highly reusable.
|
||||
</para>
|
||||
<para>
|
||||
For some systems, it may be best to provide a
|
||||
<ulink url="http://www.eaipatterns.com/CanonicalDataModel.html">Canonical Data Model</ulink>, but Spring
|
||||
Integration's general philosophy is not to require any particular format. Rather, for maximum flexibility, Spring
|
||||
Integration aims to provide the simplest possible model for extension. As with the other endpoint types, the use
|
||||
of declarative configuration in XML and/or Annotations enables simple POJOs to be adapted for the role of Message
|
||||
Transformers. These configuration options will be described below.
|
||||
<note>
|
||||
For the same reason of maximizing flexibility, Spring does not require XML-based Message payloads.
|
||||
Nevertheless, the framework does provide some convenient Transformers for dealing with XML-based payloads if
|
||||
that is indeed the right choice for your application. For more information on those transformers, see
|
||||
<xref linkend="xml"/>.
|
||||
</note>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="transformer-namespace">
|
||||
<title>The <transformer> Element</title>
|
||||
<para>
|
||||
The <transformer> element is used to create a Message-transforming endpoint. In addition to "input-channel"
|
||||
and "output-channel" attributes, it requires a "ref". The "ref" may either point to an Object that contains the
|
||||
@Transformer annotation on a single method (see below) or it may be combined with an explicit method name value
|
||||
provided via the "method" attribute.
|
||||
<programlisting language="xml"><![CDATA[<transformer id="testTransformer" ref="testTransformerBean" input-channel="inChannel"
|
||||
method="transform" output-channel="outChannel"/>
|
||||
<beans:bean id="testTransformerBean" class="org.foo.TestTransformer" />]]></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Using a "ref" attribute is generally recommended if the custom transformer handler implementation can be reused in
|
||||
other <code><transformer></code> definitions. However if the custom transformer handler implementation should
|
||||
be scoped to a single definition of the <code><transformer></code>, you can define an inner bean definition:
|
||||
<programlisting language="xml"><![CDATA[<transformer id="testTransformer" input-channel="inChannel" method="transform"
|
||||
output-channel="outChannel">
|
||||
<beans:bean class="org.foo.TestTransformer"/>
|
||||
</transformer>]]></programlisting>
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
Using both the "ref" attribute and an inner handler definition in the same <code><transformer></code>
|
||||
configuration is not allowed, as it creates an ambiguous condition and will result in an Exception being thrown.
|
||||
</para>
|
||||
</note>
|
||||
<para>
|
||||
The method that is used for transformation may expect either the <interfacename>Message</interfacename> type or
|
||||
the payload type of inbound Messages. It may also accept Message header values either individually or as a full
|
||||
map by using the @Header and @Headers parameter annotations respectively. The return value of the method can be
|
||||
any type. If the return value is itself a <interfacename>Message</interfacename>, that will be passed along to
|
||||
the transformer's output channel. If the return type is a Map, and the original Message payload was
|
||||
<emphasis>not</emphasis> a Map, the entries in that Map will be added to the Message headers of the original
|
||||
Message (the keys must be Strings). If the return value is <emphasis>null</emphasis>, then no reply Message will
|
||||
be sent (effectively the same behavior as a Message Filter returning false). Otherwise, the return value will be
|
||||
sent as the payload of an outbound reply Message.
|
||||
</para>
|
||||
<para>
|
||||
There are a also a few Transformer implementations available out of the box. Because, it is fairly common
|
||||
to use the <methodname>toString()</methodname> representation of an Object, Spring Integration provides an
|
||||
<classname>ObjectToStringTransformer</classname> whose output is a Message with a String payload. That String
|
||||
is the result of invoking the toString operation on the inbound Message's payload.
|
||||
<programlisting language="xml"><![CDATA[ <object-to-string-transformer input-channel="in" output-channel="out"/>]]></programlisting>
|
||||
A potential example for this would be sending some arbitrary object to the 'outbound-channel-adapter' in the
|
||||
<emphasis>file</emphasis> namespace. Whereas that Channel Adapter only supports String, byte-array, or
|
||||
<classname>java.io.File</classname> payloads by default, adding this transformer immediately before the
|
||||
adapter will handle the necessary conversion. Of course, that works fine as long as the result of the
|
||||
<methodname>toString()</methodname> call is what you want to be written to the File. Otherwise, you can
|
||||
just provide a custom POJO-based Transformer via the generic 'transformer' element shown previously.
|
||||
<tip>
|
||||
When debugging, this transformer is not typically necessary since the 'logging-channel-adapter' is capable
|
||||
of logging the Message payload. Refer to <xref linkend="channel-wiretap"/> for more detail.
|
||||
</tip>
|
||||
</para>
|
||||
<para>
|
||||
If you need to serialize an Object to a byte array or deserialize a byte array back into an Object,
|
||||
Spring Integration provides symmetrical serialization transformers.
|
||||
<programlisting language="xml"><![CDATA[ <payload-serializing-transformer input-channel="objectsIn" output-channel="bytesOut"/>
|
||||
|
||||
<payload-deserializing-transformer input-channel="bytesIn" output-channel="objectsOut"/>]]></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
If you only need to add headers to a Message, and they are not dynamically determined by Message content,
|
||||
then referencing a custom implementation may be overkill. For that reason, Spring Integration provides the
|
||||
'header-enricher' element. <programlisting language="xml"><![CDATA[ <header-enricher input-channel="in" output-channel="out">
|
||||
<header name="foo" value="123"/>
|
||||
<header name="bar" ref="someBean"/>
|
||||
</header-enricher>]]></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
As added convenience, Spring Integration also provides <emphasis>Object-to-Map</emphasis> and <emphasis>Map-to-Object</emphasis> transformers which
|
||||
utilize Spring Expression Language (SpEL) to serialize and de-serialize the object graphs. Object hierarchy is introspected
|
||||
to the most primitive types (e.g., String, int etc.). The path to this type is described via SpEL, which becomes the <emphasis>key</emphasis>key in the
|
||||
transformed Map with primitive type being the value.
|
||||
</para>
|
||||
<para>
|
||||
For example:
|
||||
<programlisting language="java"><![CDATA[public class Parent{
|
||||
private Child child;
|
||||
private String name;
|
||||
// setters and getters are omitted
|
||||
}
|
||||
|
||||
public class Child{
|
||||
private String name;
|
||||
private List<String> nickNames;
|
||||
// setters and getters are omitted
|
||||
}]]></programlisting>
|
||||
... will be transformed to a Map which looks like this:
|
||||
<code>{person.name=George, person.child.name=Jenna, person.child.nickNames[0]=Bimbo . . . etc}</code>
|
||||
</para>
|
||||
<para>
|
||||
SpEL-based Map allows you to describe the object structure without sharing the actual types allowing
|
||||
you to restore/rebuild the object graph into a differently typed Object graph as long as you maintain the structure.
|
||||
</para>
|
||||
<para>
|
||||
For example:
|
||||
The above structure could be easily restored back to the following Object graph via Map-to-Object transformer:
|
||||
<programlisting language="java"><![CDATA[public class Father{
|
||||
private Kid child;
|
||||
private String name;
|
||||
// setters and getters are omitted
|
||||
}
|
||||
|
||||
public class Kid{
|
||||
private String name;
|
||||
private List<String> nickNames;
|
||||
// setters and getters are omitted
|
||||
}]]></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
To configure these transformers, Spring Integration provides namespace support
|
||||
Object-to-Map:
|
||||
<programlisting language="xml"><![CDATA[<object-to-map-transformer input-channel="directInput" output-channel="output"/>]]></programlisting>
|
||||
Map-to-Object
|
||||
<programlisting language="xml"><![CDATA[<int:map-to-object-transformer input-channel="input"
|
||||
output-channel="output"
|
||||
type="org.foo.Person"/>]]></programlisting>
|
||||
or
|
||||
<programlisting language="xml"><![CDATA[<int:map-to-object-transformer input-channel="inputA"
|
||||
output-channel="outputA"
|
||||
ref="person"/>
|
||||
<bean id="person" class="org.foo.Person" scope="prototype"/>
|
||||
]]></programlisting>
|
||||
|
||||
</para>
|
||||
<note>
|
||||
NOTE: 'ref' and 'type' attributes are mutually exclusive. You can only use either one.
|
||||
Also, if using 'ref' attribute you must point to a 'prototype' scoped bean, otherwise
|
||||
BeanCreationException will be thrown.
|
||||
</note>
|
||||
</section>
|
||||
|
||||
<section id="transformer-annotation">
|
||||
<title>The @Transformer Annotation</title>
|
||||
<para>
|
||||
The <interfacename>@Transformer</interfacename> annotation can also be added to methods that expect either the
|
||||
<interfacename>Message</interfacename> type or the message payload type. The return value will be handled in the
|
||||
exact same way as described above in the section describing the <transformer> element.
|
||||
<programlisting language="java">@Transformer
|
||||
Order generateOrder(String productId) {
|
||||
return new Order(productId);
|
||||
}</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Transformer methods may also accept the @Header and @Headers annotations that is documented in <xref linkend="annotations"/>
|
||||
<programlisting language="java">@Transformer
|
||||
Order generateOrder(String productId, @Header("customerName") String customer) {
|
||||
return new Order(productId, customer);
|
||||
}</programlisting>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
Reference in New Issue
Block a user