WSO2 Enterprise Integrator 10 minutes

How to access the message context and content in WSO2 Enterprise Integrator

Rob Blaauboer
Rob Blaauboer
Integration Consultant & WSO2 Trainer
How to access the message context and content in WSO2 Enterprise Integrator
Scroll

The WSO2 Enterprise Integrator is an Enterprise Service Bus that allows you to transform and mediate messages to connect systems. An important part of the message flow through the WSO2 EI is the so-called Message Context or Synapse Message Context. This message context is the environment in which the message flows and we can access the message and of course manipulate it. That manipulation can be done in several ways. We will look at the following ways to do this:

  1. With Regular Mediation
  2. From within a Script Mediator
  3. From Java 

Regular Mediation

Regular mediation allows us to change the message context. In WSO2 we could use mediators like a payload factory mediator that will replace the payload of the message body. Later, we will focus on the properties and other ways to manipulate the message context.

From within a Script Mediator

A script mediator can be considered part of the regular mediation since it is one of the standard mediators in the Enterprise Integrator. However, it allows more flexibility because of the support of several script languages like JavaScript, Groovy and Ruby. 

Synapse uses the Apache Bean Scripting Framework for scripting language support. With the script mediator you can invoke a function in the corresponding script. With these functions, it is possible to access the Synapse message context predefined in a script variable named mc. The mc variable is a ScriptMessageContext that enables limited access to the MessageContext. This variable contains the following methods that can be accessed within the script as mc.[methodName], for instance getPayloadXML() which gets an XML representation of SOAP Body payload.

Working with a script mediator is easier than a Class mediator written in Java, which is our next possibility.

From Java 

Of course, we have control over the Message Context from Java as well. WSO2 products are written in Java so by including the right classes e.g., org.apache.synapse.MessageContext, we can access the message context. Since a Custom or Class mediator requires that a jar is added to the Enterprise Integrator and often needs a reboot, this is a bit more difficult to use. A benefit however is flexibility and more detailed manipulation of the message and its handling. It is advised to prevent implementing features that may not be supported in future versions of the product.

Focus on regular mediation

We focus therefore on regular mediation and will describe the possibilities that we have using the out-of-the-box available features. We focus on the part where the message is inside the EI and will not address the inflow or outflow of the message.

Some mediators are content aware, meaning that they access or manipulate the message context. Other mediators are content unaware, like for instance the send mediator which simply signals sending the message. Others are conditionally content aware/unaware. A <log/> mediator is unaware whereas a <log level=”full”/> accesses the message content to show it on the console and therefore is content-aware. Most mediators are (conditionally) content-aware since mediation and transformation are the goal. What is the difference between Message content and Message Context? It may be confusing given only the single letter difference. The Message Context however is the metadata carried with a message. The context controls how the transformation engine, Synapse, and the transport framework, Axis2, are behaving. 

The Message content is the actual message that is received,transformed and sent out of the product. The message content is also referred to as the message-body. 

Properties

We will focus on the setting of properties and manipulation using xpath variables like $body. We have a number of standard properties that we can set. These are: 

Synapse Message Context Properties: Allow you to get information about the message, such as the date/time it was sent, the message format, and the message operation.

SOAP Headers: Provide information about the message, such as the To and From values. These values also appear in the list of Synapse Message Context Properties.

Generic Properties: Allow you to configure messages as they are processed by the ESB profile, such as marking a message as out-only (no response message will be expected). These are more about the management of the message.

HTTP Transport Properties: Allow you to configure how the HTTP transport processes messages, such as forcing a 202 HTTP response to the client so that it stops waiting for a response. These concern again the transport of the message.

Axis2 Properties: Allow you to configure the web services engine in the ESB profile, such as specifying how to cache JMS objects, setting the minimum and maximum threads for consuming messages, and forcing outgoing HTTP/S messages to use HTTP 1.0. These properties have to do with the web engine Axis2. 

Get-property

The get-property() function allows any XPath expression used in a configuration to look up information from the current message context. Using the Property mediator, you can retrieve properties from the message context, message content, message header but also the system environment variables and the registry.

Note: It is advised to use Synapse XPath Variables if they are available for your scope. Using the Synapse XPath Variables are less strenuous on the systems’ resources. We’ll discuss these in the Shortcuts later.

The syntax of the function takes the following format:

  • get-property(String propertyName)
  • get-property(String scope, String propertyName)

Setting and getting a property (‘Test’) looks like this:

<property name="Test" scope="default" type="STRING" value="sample value"/>
 <log level="custom">
   <property expression="get-property('Test')" name="Value via get-property"/>
</log>

On the console this is the output:

[2021-04-21 11:07:52,495]  INFO {org.apache.synapse.mediators.builtin.LogMediator} – Value via get-property = sample value

Scopes

The function accepts scope as an optional parameter. It retrieves a message property at the given scope, which can be one of the following.

Synapse scopeSynapse or Default scope (taken when omitted)
axis2When the scope of a property mediator is axis2, its value is available only throughout the sequence for which the property is defined.
axis2-clientThis is similar to the synapse scope. The difference is that it can be accessed inside the  mediate() method of a mediator.
transportWhen the scope of a property mediator is transport, it will be added to the transport header of the outgoing message from the ESB profile.
registryYou can retrieve properties within the registry.
systemYou can retrieve Java System properties.
operationThis scope is available while the operation is active. You can use these to transfer information into and out of an iterate/aggregate mediator.
defaultIf no specific scope is defined then the default scope is applied, this is also known as the synapse scope.

If you provide only the property name without the scope, the default scope will be used.

Shortcuts

We have several so-called shortcuts, or XPath variables as WSO2 calls them, that allows us to forgo the get-property synapse command. There is a set of predefined XPath variables that you can directly use to write access areas of the Message Context or Message Content. These XPath variables get properties of various scopes as follows:

$bodyThe message body element. For example, the expression $body//getQuote refers to the first getQuote element in a SOAP body
$headerThe SOAP 1.1 or 1.2 header element. For example, the expression $header/wsa:To refers to the addressing To header
$axis2Prefix for Axis2 MessageContext properties. This is used to get the property value at the axis2 scope
$ctxPrefix for Synapse MessageContext properties and gets a property at the default scope
$trpPrefix used to get the transport headers. For example, to get the transport header named Content-Type of the current message, use the XPath expression $trp:Content-Type
$urlThe prefix used to get the URI element of a request URL
$funcThe prefix used to refer to a particular parameter value passed externally by an invoker such as the Call Template Mediator
$envPrefix used to get a SOAP 1.1 or 1.2 envelope level element

An example

What can we do with all this information? Well, let us explain it with an example. 

We have a simple proxy that receives the following XML message:

<VatNumbers xmlns="http://yenlo.com/blog">
  <VatNumber>
    <country>AT</country>
    <vat>U34275908</vat>
  </VatNumber>
  <VatNumber>
    <country>BE</country>
    <vat>98235273941</vat>
  </VatNumber>
  <VatNumber>
    <country>DE</country>
    <vat>432256432</vat>
  </VatNumber>
</VatNumbers>

The source code of the proxy is straightforward and kept simple:

<?xml version="1.0" encoding="UTF-8"?>
<proxy name="mcExample" startOnLoad="true" transports="http https"
  xmlns="http://ws.apache.org/ns/synapse"
  xmlns:ns="http://yenlo.com/blog">
  <target>
    <inSequence>
      <log level="custom">
        <property name="Value" expression="$body//ns:VatNumbers" /> <!-- #1 -->
      </log>
      <property name="Test" value="sample value"/>
      <log level="custom">
        <property name="Content Type via $trp" expression="$trp:Content-Type" /> <!-- #2 -->
        <property name="Value via get-property" expression="get-property('Test')" /> <!-- #3 -->
      </log>
      <foreach expression="$body//ns:VatNumber">
        <sequence>
          <log level="custom">
            <property name="Country" expression="$body//ns:country" />
          </log>
        </sequence>
      </foreach>
      <respond/>
    </inSequence>
  </target>
</proxy>

On line #1 we access the message body and reference all VatNumbers-elements in the message.

On line #2 we access a transport-header, the HTTP Content-Type to be specific, and log it.

On line #3 we use the get-property function to access the value of the Test property.

In the foreach mediator it’s demonstrated that the $body references other parts of the message body depending on the situation where it’s used.

When we send the message into the proxy and look at the wso2carbon.log we can see these Message Context examples in action (cleaned up for better reading):

[2021-04-21 11:43:35,195]  INFO {org.apache.synapse.mediators.builtin.LogMediator} –

Value = <VatNumbers xmlns=”http://yenlo.com/blog”><VatNumber><country>AT</country><vat>U34275908</vat></VatNumber><VatNumber><country>BE</country><vat>98235273941</vat></VatNumber><VatNumber><country>DE</country><vat>432256432</vat></VatNumber></VatNumbers>, Content Type via $trp = text/xml; charset=UTF-8,

Value via get-property = sample value
[2021-04-21 11:43:35,196]  INFO {org.apache.synapse.mediators.builtin.LogMediator} – Country = AT
[2021-04-21 11:43:35,196]  INFO {org.apache.synapse.mediators.builtin.LogMediator} – Country = BE
[2021-04-21 11:43:35,197]  INFO {org.apache.synapse.mediators.builtin.LogMediator} – Country = DE

In the last three log lines we see that the $body now references one VatNumber-element due to the foreach that loops through each of those elements.  

Conclusion

This blog explains ways to manipulate the Message Context and the Message Content. There are mediators shipped with WSO2 Enterprise Integrator that can be used to manipulate both the message context as well as the message content but also as custom mediators could be developed if the shipped mediators are not sufficient.

There are various ways to access parts of the Message Contexts and the Message content and there exist several XPath variables to do so. Some of these are demonstrated in an example proxy.

Accessing the message context is easy with the $ variables defined in the Enterprise Integrator. We can quickly retrieve information, for instance in the body of the message. 

Happy integrating!