Demystifying Apache Synapse Mediators: A Hands-On Guide
Apache Synapse is a versatile and powerful Enterprise Service Bus (ESB) that facilitates seamless integration and communication between different systems and services. One of the key components that make Apache Synapse so adaptable is its Mediators. In this comprehensive blog, we will explore the concept of Mediators, understand their types, and dive into hands-on examples showcasing their practical applications.
Table of Contents:
What are Mediators in Apache Synapse?
Built-in Mediators in Apache Synapse 2.1. Filter Mediator 2.2. Log Mediator 2.3. Callout Mediator 2.4. Enrich Mediator 2.5. Script Mediator
Mediator Sequences 3.1. Creating a Custom Mediator Sequence
Conclusion
1. What are Mediators in Apache Synapse?
Mediators are fundamental units of processing within Apache Synapse. They are responsible for modifying, filtering, transforming, and routing messages as they flow through the ESB. Mediators play a vital role in ensuring message integrity, security, and facilitating various integration patterns.
2. Built-in Mediators in Apache Synapse:
Apache Synapse offers a rich set of built-in Mediators catering to different integration requirements. Let's explore some of the essential Mediators and their applications:
2.1. Filter Mediator:
The Filter Mediator allows us to route messages based on specific criteria. It evaluates conditions and determines whether the message should follow a particular path or be discarded.
Hands-on Example: Let's consider an API that receives customer orders. We want to filter out orders with a total amount below $100 to reduce load on the backend system.
<api xmlns="http://ws.apache.org/ns/synapse" name="OrderApi" context="/order">
<resource methods="POST">
<inSequence>
<filter source="$body//totalAmount" regex="^(?!100\.00$)\d+\.\d{2}$">
<then>
<!-- Process the valid order -->
<send>
<endpoint>
<http method="post" uri-template="http://backend-api.com/processOrder"/>
</endpoint>
</send>
</then>
<else>
<!-- Discard the order -->
<log level="custom">
<property name="OrderStatus" value="Rejected"/>
</log>
</else>
</filter>
</inSequence>
</resource>
</api>
In this example, the Filter Mediator examines the "totalAmount" element in the incoming order message. If the total amount is not exactly $100.00, it proceeds to process the order by sending it to the backend API. Otherwise, it discards the order and logs the rejection status.
2.2. Log Mediator:
The Log Mediator is a valuable tool for debugging and monitoring. It allows us to log messages and their properties during the message flow.
Hands-on Example: We want to log incoming messages, including the timestamp, request payload, and the source IP address.
<api xmlns="http://ws.apache.org/ns/synapse" name="LogApi" context="/log">
<resource methods="POST">
<inSequence>
<log level="full">
<property name="Timestamp" expression="get-property('SYSTEM_TIME')"/>
<property name="RequestPayload" expression="$body"/>
<property name="SourceIP" expression="get-property('axis2', 'REMOTE_ADDR')"/>
</log>
<!-- Continue with message processing -->
<send/>
</inSequence>
</resource>
</api>
In this example, the Log Mediator records the timestamp, request payload, and source IP address of the incoming message. This information can be used for debugging or monitoring the system's behavior.
2.3. Callout Mediator:
The Callout Mediator allows us to invoke external services and incorporate their responses into the message flow.
Hands-on Example: Let's create an API that calls an external weather service to enrich the incoming message with weather data before forwarding it to the backend system.
<api xmlns="http://ws.apache.org/ns/synapse" name="WeatherApi" context="/weather">
<resource methods="POST">
<inSequence>
<!-- Call the weather service to get weather data -->
<callout serviceURL="http://weather-api.com/getWeather">
<source-type>envelope</source-type>
<target-property>weatherResponse</target-property>
</callout>
<!-- Enrich the original message with weather data -->
<enrich>
<source type="property" property="weatherResponse"/>
<target type="body"/>
</enrich>
<!-- Continue with the enriched message -->
<send/>
</inSequence>
</resource>
</api>
In this example, the Callout Mediator fetches weather data from an external weather service and stores the response in a property named "weatherResponse." The Enrich Mediator then adds this weather data to the original message before forwarding it to the backend system.
2.4. Enrich Mediator:
The Enrich Mediator allows us to add information from external sources to the original message, enriching its content.
Hands-on Example: Suppose we have a service that receives customer information and needs to enrich the message with additional data from a customer database.
<api xmlns="http://ws.apache.org/ns/synapse" name="CustomerApi" context="/customer">
<resource methods="POST">
<inSequence>
<!-- Fetch customer data from the database -->
<enrich>
<source type="custom" clone="true" xpath="getCustomerData($body//customerId)"/>
<target type="body" action="child"/>
</enrich>
<!-- Continue with the enriched message -->
<send/>
</inSequence>
</resource>
</api>
In this example, the Enrich Mediator invokes a custom function "getCustomerData" that queries the customer database based on the "customerId" extracted from the incoming message. The enriched customer data is then added to the original message before processing it further.
2.5. Script Mediator:
The Script Mediator allows us to write custom scripts (e.g., JavaScript) to manipulate messages based on complex logic.
Hands-on Example: Suppose we want to create a custom API that filters orders based on certain criteria using a JavaScript script.
<api xmlns="http://ws.apache.org/ns/synapse" name="CustomOrderApi" context="/customorder">
<resource methods="POST">
<inSequence>
<!-- Execute the custom JavaScript logic -->
<script language="js">
<![CDATA[
var orderAmount = parseFloat(mc.getProperty('ORDER_AMOUNT'));
if (orderAmount >= 500) {
mc.setProperty('HIGH_VALUE_ORDER', 'true');
} else {
mc.setProperty('HIGH_VALUE_ORDER', 'false');
}
]]>
</script>
<!-- Continue with the message processing -->
<send/>
</inSequence>
</resource>
</api>
In this example,
the Script Mediator runs a JavaScript code snippet that checks the order amount (stored in the property 'ORDER_AMOUNT') and sets the 'HIGH_VALUE_ORDER' property to 'true' if the order amount is greater than or equal to $500; otherwise, it sets it to 'false.'
3. Mediator Sequences:
Mediator Sequences are reusable sets of Mediators that can be applied to message flows. They help in encapsulating common logic and promoting reusability across different services.
3.1. Creating a Custom Mediator Sequence:
Suppose we want to implement a common authentication sequence for multiple APIs.
<sequence xmlns="http://ws.apache.org/ns/synapse" name="AuthSequence">
<header name="Authorization" expression="fn:concat('Bearer ', $ctx:jwtToken)"/>
<send/>
</sequence>
In this example, we create a sequence called "AuthSequence" that adds an "Authorization" header to the outgoing message with a JWT token (stored in the context variable 'jwtToken'). We can now apply this sequence to any API that requires authentication by referencing it in the API configuration.
Conclusion:
In this blog, we've explored the world of Apache Synapse Mediators and their essential role in message processing. We've covered various built-in Mediators such as Filter, Log, Callout, Enrich, and Script, along with practical examples showcasing their applications.
Apache Synapse Mediators provide a powerful toolkit to handle complex integration scenarios, enabling developers to create robust and flexible ESB solutions. Understanding the different types of Mediators and how to use them effectively will significantly enhance your integration projects with Apache Synapse.
Remember, this blog is just an introduction to Apache Synapse Mediators. To dive deeper and explore more advanced use cases, refer to the official Apache Synapse documentation [https://synapse.apache.org/userguide/mediators.html].
Happy integrating!