Monday, March 27, 2017

How to write Axis2 handler to validate the request payload and send back the response to the client?

In this article I'm going to cover below areas...
  1. How to write a custom Axis2 handler
  2. How to get the request payload
  3. How to validate payload (In this example, I'm checking whether the payload is a valid JSON or not)
  4. Respond to the customer without invoking the mediation flow.
Implement the handler class with extending the AbstractHandler class and implementing the Handler interface.

package com.wso2.handler.sample;

import net.minidev.json.parser.JSONParser;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.engine.AxisEngine;
import org.apache.axis2.engine.Handler;
import org.apache.axis2.handlers.AbstractHandler;
import org.apache.commons.io.IOUtils;
import org.apache.synapse.transport.passthru.util.RelayUtils;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.soap.SOAP11Constants;
import org.apache.axiom.soap.SOAP12Constants;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPFault;
import org.apache.axiom.soap.SOAPFaultCode;
import org.apache.axiom.soap.SOAPFaultDetail;
import org.apache.axiom.soap.SOAPFaultReason;
import org.apache.axis2.util.MessageContextBuilder;

import javax.xml.namespace.QName;

import java.io.InputStream;
import java.io.StringWriter;

/**
 * Created by tharanga on 3/24/17.
 */
public class SampleAxis2Handler extends AbstractHandler implements Handler {

    public InvocationResponse invoke(MessageContext messageContext) throws AxisFault {
        try {

            RelayUtils.buildMessage(messageContext);

            InputStream jsonPaylodStream = (InputStream) (messageContext).getProperty(
                            "org.apache.synapse.commons.json.JsonInputStream");
            StringWriter writer = new StringWriter();
            IOUtils.copy(jsonPaylodStream, writer);
            String payloadMessge = writer.toString();

            try {
                //Validate the json message.
                JSONParser jsonParser = new JSONParser();
                jsonParser.parse(payloadMessge);

                System.out.println(messageContext.getEnvelope().getBody().toString());
                return InvocationResponse.CONTINUE;
            } catch (Exception ex) {
                AxisFault _axisFault = createAxisFault(messageContext, ex);
                MessageContext _faultContext = MessageContextBuilder.createFaultMessageContext(messageContext, _axisFault);
                _faultContext.setProperty("HTTP_SC", "400");

                AxisEngine.sendFault(_faultContext);
                return InvocationResponse.ABORT;
            }


        } catch (Exception e) {
            e.printStackTrace();
        }

        return InvocationResponse.ABORT;
    }

    private AxisFault createAxisFault(MessageContext context, Throwable e) {

        SOAPFactory soapFactory;
        String namespace;
        if (context.isSOAP11()) {
            soapFactory = OMAbstractFactory.getSOAP11Factory();
            namespace = SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI;
        } else {
            soapFactory = OMAbstractFactory.getSOAP12Factory();
            namespace = SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI;
        }
        SOAPFault fault = soapFactory.createSOAPFault();

        SOAPFaultCode soapFaultCode = soapFactory.createSOAPFaultCode();
        soapFaultCode.setText(new QName(namespace, "Server", "soapenv"));

        SOAPFaultReason soapFaultReason = soapFactory.createSOAPFaultReason();
        soapFaultReason.setText("Error while mediate message: " + e.getMessage());

        SOAPFaultDetail soapFaultDetail = soapFactory.createSOAPFaultDetail();
        soapFaultDetail.setText("Invalid message");
        fault.setCode(soapFaultCode);
        fault.setDetail(soapFaultDetail);
        fault.setReason(soapFaultReason);

        return new AxisFault(fault);
    }
}


In the above sample, I'm validating the JSON message and if it fails, send the 400 HTTP response code to the client.

Find the sample test result below



  • Payload with valid JSON message
[2017-03-24 17:10:18,271] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "POST /services/Proxy1 HTTP/1.1[\r][\n]"
[2017-03-24 17:10:18,271] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Host: tharanga:8280[\r][\n]"
[2017-03-24 17:10:18,271] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Connection: keep-alive[\r][\n]"
[2017-03-24 17:10:18,271] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Content-Length: 19[\r][\n]"
[2017-03-24 17:10:18,272] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Postman-Token: e2997992-9a63-6858-3afc-9095f7348130[\r][\n]"
[2017-03-24 17:10:18,272] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Cache-Control: no-cache[\r][\n]"
[2017-03-24 17:10:18,272] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Origin: chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop[\r][\n]"
[2017-03-24 17:10:18,272] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36[\r][\n]"
[2017-03-24 17:10:18,272] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Content-Type: application/json[\r][\n]"
[2017-03-24 17:10:18,272] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Accept: */*[\r][\n]"
[2017-03-24 17:10:18,273] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Accept-Encoding: gzip, deflate[\r][\n]"
[2017-03-24 17:10:18,273] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Accept-Language: en-US,en;q=0.8[\r][\n]"
[2017-03-24 17:10:18,273] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "[\r][\n]"
[2017-03-24 17:10:18,273] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "{"name":"tharanga"}"
tharanga
[2017-03-24 17:10:18,275]  INFO - LogMediator status = 11111111111111111111111111111111111111111111
[2017-03-24 17:10:18,276] DEBUG - wire HTTP-Listener I/O dispatcher-1 << "HTTP/1.1 202 Accepted[\r][\n]"
[2017-03-24 17:10:18,277] DEBUG - wire HTTP-Listener I/O dispatcher-1 << "Date: Fri, 24 Mar 2017 11:40:18 GMT[\r][\n]"
[2017-03-24 17:10:18,277] DEBUG - wire HTTP-Listener I/O dispatcher-1 << "Transfer-Encoding: chunked[\r][\n]"
[2017-03-24 17:10:18,277] DEBUG - wire HTTP-Listener I/O dispatcher-1 << "Connection: keep-alive[\r][\n]"
[2017-03-24 17:10:18,277] DEBUG - wire HTTP-Listener I/O dispatcher-1 << "[\r][\n]"
[2017-03-24 17:10:18,277] DEBUG - wire HTTP-Listener I/O dispatcher-1 << "0[\r][\n]"
[2017-03-24 17:10:18,277] DEBUG - wire HTTP-Listener I/O dispatcher-1 << "[\r][\n]"



  • Payload with invalid JSON message
[2017-03-24 17:10:26,709] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "POST /services/Proxy1 HTTP/1.1[\r][\n]"
[2017-03-24 17:10:26,709] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Host: tharanga:8280[\r][\n]"
[2017-03-24 17:10:26,709] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Connection: keep-alive[\r][\n]"
[2017-03-24 17:10:26,709] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Content-Length: 17[\r][\n]"
[2017-03-24 17:10:26,710] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Postman-Token: 9f7fc1bb-be03-e321-b773-62bea5fce577[\r][\n]"
[2017-03-24 17:10:26,710] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Cache-Control: no-cache[\r][\n]"
[2017-03-24 17:10:26,710] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Origin: chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop[\r][\n]"
[2017-03-24 17:10:26,710] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36[\r][\n]"
[2017-03-24 17:10:26,710] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Content-Type: application/json[\r][\n]"
[2017-03-24 17:10:26,710] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Accept: */*[\r][\n]"
[2017-03-24 17:10:26,710] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Accept-Encoding: gzip, deflate[\r][\n]"
[2017-03-24 17:10:26,710] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Accept-Language: en-US,en;q=0.8[\r][\n]"
[2017-03-24 17:10:26,710] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "[\r][\n]"
[2017-03-24 17:10:26,711] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "{"name":"tharanga"
[2017-03-24 17:10:26,742] DEBUG - wire HTTP-Listener I/O dispatcher-1 << "HTTP/1.1 400 Bad Request[\r][\n]"
[2017-03-24 17:10:26,742] DEBUG - wire HTTP-Listener I/O dispatcher-1 << "Content-Type: application/json; charset=UTF-8[\r][\n]"
[2017-03-24 17:10:26,743] DEBUG - wire HTTP-Listener I/O dispatcher-1 << "Date: Fri, 24 Mar 2017 11:40:26 GMT[\r][\n]"
[2017-03-24 17:10:26,743] DEBUG - wire HTTP-Listener I/O dispatcher-1 << "Transfer-Encoding: chunked[\r][\n]"
[2017-03-24 17:10:26,743] DEBUG - wire HTTP-Listener I/O dispatcher-1 << "Connection: Close[\r][\n]"
[2017-03-24 17:10:26,743] DEBUG - wire HTTP-Listener I/O dispatcher-1 << "[\r][\n]"
[2017-03-24 17:10:26,743] DEBUG - wire HTTP-Listener I/O dispatcher-1 << "99[\r][\n]"
[2017-03-24 17:10:26,743] DEBUG - wire HTTP-Listener I/O dispatcher-1 << "{"Fault":{"faultcode":"soapenv:Server","faultstring":"Error while mediate message: Unexpected End Of File position 17: null","detail":"Invalid message"}}[\r][\n]"
[2017-03-24 17:10:26,744] DEBUG - wire HTTP-Listener I/O dispatcher-1 << "0[\r][\n]"
[2017-03-24 17:10:26,744] DEBUG - wire HTTP-Listener I/O dispatcher-1 << "[\r][\n]"



No comments:

Post a Comment