In this tutorial, we will explain step by step how to write a Synapse Handler using WSO2 Enterprise Integrator.
What is a custom Synapse Handler?
A custom synapse handler can be used to process each individual request in a specific manner. The handler enables callbacks to be registered in the following scenarios:

- Request in flow: This executes when the request reaches the synapse handler.
public boolean handleRequestInFlow(MessageContext messageContext);
- Request out flow: This executes when the request leaves the synapse handler.
public boolean handleRequestOutFlow(MessageContext messageContext);
- Response in flow: This executes when the response reaches the synapse handler.
public boolean handleResponseInFlow(MessageContext messageContext);
- Response out flow: This executes when the response leaves the synapse handler.
public boolean handleResponseOutFlow(MessageContext messageContext);
How to create a Synapse Handler
1.In order to write a synapse handler create a new project with the following Maven dependencies added:
<repositories>
<repository>
<id>wso2-nexus</id>
<name>WSO2 internal Repository</name>
<url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>
<releases>
<enabled>true</enabled>
<updatePolicy>daily</updatePolicy>
<checksumPolicy>ignore</checksumPolicy>
</releases>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.apache.synapse</groupId>
<artifactId>synapse-core</artifactId>
<version>2.1.7-wso2v143</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>org.apache.axis2.wso2</groupId>
<artifactId>axis2</artifactId>
<version>1.6.1-wso2v41</version>
</dependency>
</dependencies>
2. Once the dependencies have been addressed, extend the rg.apache.synapse.AbstractSynapseHandler class and create the necessary callbacks:
public class CustomHandler extends AbstractSynapseHandler {
private final static Log log = LogFactory.getLog(CustomHandler.class);
public boolean handleRequestInFlow(MessageContext messageContext) {
if (log.isDebugEnabled()) {
log.info("handleRequestInFlow");
}
return true;
}
public boolean handleRequestOutFlow(MessageContext messageContext) {
if (log.isDebugEnabled()) {
log.info("handleRequestOutFlow");
}
return true;
}
public boolean handleResponseInFlow(MessageContext messageContext) {
if (log.isDebugEnabled()) {
log.info("handleResponseInFlow");
}
return true;
}
public boolean handleResponseOutFlow(MessageContext messageContext) {
if (log.isDebugEnabled()) {
log.info("handleResponseOutFlow");
}
return true;
}
}
3. Then compile the project using the following command:
mvn clean install
Synapse Handler Installation
1.When the compilation ends, copy the jar created in the lib folder into Enterprise Integrator or Micro Integrator:
cp ${HANDLER_HOME}/target/com.chakray.integrator.handler-1.0.jar ${INTEGRATOR}/lib
2. In order to enable the Custom Handler, edit the ${INTEGRATOR}/conf/synapse-handlers.xml file and add the following line:
<handler name="CustomHandler" class="com.chakray.integrator.handler.CustomHandler"/>

3. Add the corresponding loggers by attaching the following lines to the ${INTEGRATOR}/conf/log4j2.properties file:
loggers = custom-handler, AUDIT_LOG... ... logger.custom-handler.name=com.chakray.integrator.handler.CustomHandler logger.custom-handler.level=DEBUG

4. Launch Integrator once all changes have been applied. For each request performed, a log is created on each callback:

Handler Uses
Headers
One of the most common uses of handlers is the reading, modification, or deletion of headers during the request.
Read headers in the request in flow handleRequestInFlow:
org.apache.axis2.context.MessageContext axis2MessageContext = ((Axis2MessageContext) messageContext)
.getAxis2MessageContext();
// Read headers from request
Object headers = axis2MessageContext
.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);
log.info("Headers from request");
for (Object header: ((Map) headers).entrySet()) {
log.info(header);
}

- Add a new header/cookie (JSESSIONID) to the response in flow handleResponseOutFlow:
org.apache.axis2.context.MessageContext axis2MessageContext = ((Axis2MessageContext) messageContext)
.getAxis2MessageContext();
// Add new header to response
Map headers = (Map) axis2MessageContext.getProperty(
org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS
);
String session = Constants.SESSION_COOKIE_JSESSIONID + "=" + System.currentTimeMillis();
headers.put("Cookie", session);
messageContext.setProperty(
org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS, headers
);
log.info("Headers from response");
for (Object header: ((Map) axis2MessageContext.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS) ).entrySet()) {
log.info(header);
}

Body
Another possible Handler use is the reading or modification of the body of the request or response.
- Read the body of the request in flow handleRequestOutFlow:
try {
RelayUtils.buildMessage(((Axis2MessageContext) messageContext).getAxis2MessageContext());
} catch (Exception e) {
log.error(e.getMessage());
}
// Read body request
log.info("Body from request");
log.info(
messageContext.getEnvelope().getBody().toString()
);
OMElement ns = messageContext.getEnvelope().getBody().getFirstElement();
log.info("Parameters from request");
if (ns != null) {
Iterator parameters = ns.getChildElements();
while (parameters.hasNext()) {
OMElement param = (OMElement) parameters.next();
log.info("Key: " + param.getQName());
log.info("Value: " + param.getText());
}
}

- Modify the body of the response. In this example, we use a service that restores user attributes and the handler replaces the user password with “*****“. E.g.
try {
RelayUtils.buildMessage(((Axis2MessageContext) messageContext).getAxis2MessageContext());
} catch (Exception e) {
log.error(e.getMessage());
}
// Read body response
log.info("Body from response");
log.info(
messageContext.getEnvelope().getBody().toString()
);
OMElement ns = messageContext.getEnvelope().getBody().getFirstElement();
log.info("Parameters from response");
if (ns != null) {
Iterator parameters = ns.getChildElements();
while (parameters.hasNext()) {
OMElement param = (OMElement) parameters.next();
Iterator it = param.getChildElements();
while (it.hasNext()) {
OMElement attribute = (OMElement) it.next();
log.info("Attribute: " + attribute.getLocalName());
log.info("Value: " + attribute.getText());
String localName = attribute.getLocalName();
// Replace user password with ***
if (localName.equals("UM_USER_PASSWORD") ||
localName.equals("UM_SALT_VALUE")) {
attribute.setText("*****");
}
}
}
}








