Ir al contenido principal

Cómo crear un Synapse Handler | WSO2 Enterprise Integrator

En este tutorial os explicaremos paso a paso cómo crear un Synapse Handler con WSO2 Enterprise Integrator.

¿Qué es un Custom Synapse Handler?

Un custom synapse handler se puede utilizar para procesar cada uno de los requests de forma personalizada. El handler permite registrar los callback de los siguientes eventos:

  • Request in flow: Se ejecuta cuando el request entra a Synapse

public boolean handleRequestInFlow(MessageContext messageContext);
  • Request out flow: Se ejecuta cuando el request sale de Synapse

public boolean handleRequestOutFlow(MessageContext messageContext);
  • Response in flow: Se ejecuta cuando el response entra a Synapse

public boolean handleResponseInFlow(MessageContext messageContext);
  • Response out flow: Se ejecuta cuando el response sale de Synapse

public boolean handleResponseOutFlow(MessageContext messageContext);

Cómo crear un Synapse Handler

1.Para crear un Synapse Handler se debe crear un nuevo proyecto y agregar las siguientes dependencias de Maven:

<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. Una vez resueltas las dependencias extendemos la clase org.apache.synapse.AbstractSynapseHandler y creamos los callbacks necesarios:

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. Compilamos el proyecto usando el siguiente comando:

mvn clean install

Instalación de Synapse Handler

1.Al finalizar la compilación copiamos el jar generado en la carpeta lib dentro de Enterprise Integrator o Micro Integrator:

cp ${HANDLER_HOME}/target/com.chakray.integrator.handler-1.0.jar ${INTEGRATOR}/lib

2. Para habilitar el Custom Handler editamos el archivo ${INTEGRATOR}/conf/synapse-handlers.xml y agregamos la siguiente línea:

<handler name="CustomHandler" class="com.chakray.integrator.handler.CustomHandler"/>

3. Agregamos los loggers correspondientes agregando al archivo ${INTEGRATOR}/conf/log4j2.properties las siguientes líneas:

loggers = custom-handler, AUDIT_LOG...
...
logger.custom-handler.name=com.chakray.integrator.handler.CustomHandler
logger.custom-handler.level=DEBUG

4. Al tener aplicados todos los cambios iniciamos Integrator. Por cada request que realizamos veremos los logs colocados en cada uno de los callback:

Usos del Handler

Headers

Uno de los usos que se le puede dar a los handlers es leer, modificar o eliminar las cabeceras durante el request.

  • Leer cabeceras en el request dentro del flujo 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);
}

  • Agregar una nueva cabecera/cookie (JSESSIONID) al response en el flujo 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

Otro posible uso del Handler es leer o modificar el cuerpo del request o response

  • Leer el body del request en el flujo 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());
    }
}

  • Modificar el body del response, en este ejemplo consumimos un servicio que devuelve todos los atributos de un usuario y el handler reemplaza la contraseña del usuario con “*****“ Ej:

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