You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 7 Next »

Unknown macro: {span}

Transformation Feature

The CXF Transformation feature provides for a flexible and fast way to do the dynamic transformations of the inbound and/or outbound XML messages.

This feature can be used in a number of cases: dropping the namespace of the outbound messages, qualifying the incoming message, changing namespaces, appending or dropping elements and converting attributes to elements.

The "outTransformElements", "inTransformElements", "outDropElements", "inDropElements", "outAppendElements", "inAppendElements" and "attributesAsElements" properties can be used.

Spring configuration

Changing input and output element names and namespaces

"outTransformElements" map property can be used to change the output element names and change or drop namespaces. Keys are the elements to be changed, values are the new element names. Example:

<bean id="transformFeature" class="org.apache.cxf.feature.StaxTransformFeature">
  <property name="outTransformElements">
    <map>
      <!-- change "book" to "thebook" -->
      <entry key="book" value="thebook"/>
      
      <!-- drop the namespace from "book" -->
      <entry key="{http://books}book" value="book"/> 
      
      <!-- qualify "book" with "http://books" -->
      <entry key="book" value="{http://books}thebook"/> 
      
      <!--  change namespace to "http://books" for all the elements with the "http://book" namespace -->
      <entry key="{http://book}*" value="{http://books}*"/> 
    </map>
  </property>
</bean> 

"inTransformElements" map property can be used to change the input element names and change or drop namespaces. See the "outTransfromElements" property description for an example.

Appending new output elements

"outAppendElements" map property can be used to append new simple or qualified elements to the output. Keys are the elements the new elements will be appended before, values are the new elements. Examples:

<bean id="transformFeature" class="org.apache.cxf.feature.StaxTransformFeature">
  <property name="outAppendElements">
    <map>
      <!-- get "book" wrapped with the new "thebook" element-->
      <entry key="book" value="thebook"/>
    </map>
  </property>
</bean> 

Only this so-called Append-Wrap is currently supported for out elements.

Appending new input elements

"inAppendElements" map property can be used to append new simple or qualified elements to the input in a number of ways.

Append-Pre-Wrap

<bean id="transformFeature" class="org.apache.cxf.feature.StaxTransformFeature">
  <property name="inAppendElements">
    <map>
      <!-- get "book" wrapped with the new "thebook" element-->
      <entry key="book" value="thebook"/>
    </map>
  </property>
</bean> 

Append-Post-Wrap

<bean id="transformFeature" class="org.apache.cxf.feature.StaxTransformFeature">
  <property name="inAppendElements">
    <map>
      <!-- 
         get all "book" children elements wrapped with the new "thebook" element
         using the "/" convention.
      -->
      <entry key="book/" value="thebook"/>
    </map>
  </property>
</bean> 

Append-Pre-Include

<bean id="transformFeature" class="org.apache.cxf.feature.StaxTransformFeature">
  <property name="inAppendElements">
    <map>
      <!-- append new simple "thebook" element with a text value '2' before "the book" -->
      <entry key="book" value="thebook=2"/>
    </map>
  </property>
</bean> 

Append-Post-Include

<bean id="transformFeature" class="org.apache.cxf.feature.StaxTransformFeature">
  <property name="inAppendElements">
    <map>
      <!-- append new simple "thebook" element with a text value '2' after "the book", using a '/' convention -->
      <entry key="book/" value="thebook=2"/>
    </map>
  </property>
</bean> 

Replacing text content

It's possible to replace the text content of a given simple element only on the input, for example:

<bean id="transformFeature" class="org.apache.cxf.feature.StaxTransformFeature">
  <property name="inAppendElements">
    <map>
      <!-- replace the text content of {ns}a element with the 'new Text' value -->
      <entry key="{ns}a" value="{ns}a=new Text"/>
    </map
  </property>
</bean> 

Dropping output elements

"outDropElements" list property can be used to drop output elements. Note that children elements if any of a given dropped element are not affected. Examples:

<bean id="transformFeature" class="org.apache.cxf.feature.StaxTransformFeature">
  <property name="outDropElements">
    <list>
      <!-- shallow drop 'index' and '{http://numbers}number' elements -->
      <value>{http://numbers}number</value>
      <value>index</value>
    </list>
  </property>
</bean> 

Dropping input elements

"inDropElements" list property can be used to drop input elements. Note that children elements if any of a given dropped element are not affected. Please see the "outDropElements" property description for an example.

Additionally, inTransformElements property can be used to deep-drop an element and all of its children if any, for example:

<bean id="transformFeature" class="org.apache.cxf.feature.StaxTransformFeature">
  <property name="outTransformElements">
    <map>
      <!-- drop "book" and all of its children, using an empty value convention -->
      <entry key="book" value=""/>
       
    </map>
  </property>
</bean> 

Converting attributes to elements

"attributesAsElements" boolean property can be used to have attributes serialized as elements on the output only.

The combination of "attributesAsElements" and "outDropElements" properties can be used to have certain attributes ignored in the output by turning them into elements and then blocking them.

Input Transformation and Redirection

Consider the case where a new endpoint has been introduced but some of the existing clients have not been updated yet to work with the new endpoint, they are still unaware of it.

In this case you may want to keep the CXFServlet serving the old clients but make it redirect them to a new CXFServlet serving a new endpoint only.
Now, in order to serve the old clients one needs to apply a transform feature, however the new clients should not be affected. Thus the feature can be configured such that it's only triggered if a certain contextual property has been set on a current Message. In this case the feature should only apply to the old redirected clients:

<bean id="transformFeatureRest" class="org.apache.cxf.feature.StaxTransformFeature">
      <!-- 
         apply the transformation only if the boolean property with the given name
         is set to true on the message
      -->   
      <property name="contextPropertyName" value="http.service.redirection"/>
      <!-- the transform configuration -->
</bean>

Configuring the feature from the code

The feature can be configured from the code for JAX-WS or JAX-RS clients and endpoints.

JAX-WS

Here is how a JAX-WS client can be configured:

CustomerServiceService service = new CustomerServiceService();
CustomerService customerService = service.getCustomerServicePort();
Client client = ClientProxy.getClient(customerService);

// drop namespace from all elements qualified by 'http://customers'
Map<String, String> outTransformMap = Collections.singletonMap("{http://customers}*", "*");
org.apache.cxf.interceptor.transform.TransformOutInterceptor transformOutInterceptor =
    new org.apache.cxf.interceptor.transform.TransformOutInterceptor();
transformOutInterceptor.setOutTransformElements(outTransformMap);
client.getOutInterceptors().add(transformOutInterceptor);

// qualify the incoming 'customer' element with 'http://customers' 
Map<String, String> inTransformMap =  Collections.singletonMap("customer", "{http://customers}customer");
org.apache.cxf.interceptor.transform.TransformInInterceptor transformInInterceptor =
    new org.apache.cxf.interceptor.transform.TransformInInterceptor();
transformInInterceptor.setInTransformElements(inTransformMap);
client.getInInterceptors().add(transformInInterceptor);

JAX-RS

Here is how a JAX-RS client can be configured:

CustomerService customerServiceProxy = JAXRSClientFactory.create(endpointAddress, CustomerService.class);

ClientConfiguration config = WebClient.getConfig(customerServiceProxy);

// or
//WebClient client = WebClient.create(endpointAddress);
//ClientConfiguration config = WebClient.getConfig(client);


// drop namespace from all elements qualified by 'http://customers'
Map<String, String> outTransformMap = Collections.singletonMap("{http://customers}*", "*");
org.apache.cxf.interceptor.transform.TransformOutInterceptor transformOutInterceptor =
    new org.apache.cxf.interceptor.transform.TransformOutInterceptor();
transformOutInterceptor.setOutTransformElements(outTransformMap);
config.getOutInterceptors().add(transformOutInterceptor);

// qualify the incoming 'customer' element with 'http://customers' 
Map<String, String> inTransformMap =  Collections.singletonMap("customer", "{http://customers}customer");
org.apache.cxf.interceptor.transform.TransformInInterceptor transformInInterceptor =
    new org.apache.cxf.interceptor.transform.TransformInInterceptor();
transformInInterceptor.setInTransformElements(inTransformMap);
config.getInInterceptors().add(transformInInterceptor);
  • No labels