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("*****"); } } } }