December 17, 2015

Customize APIM Gateway Errors

Gateway is the underlying synapse engine in APIM that can take the responsibility of performing throttling, authentication, etc in order to manage the API [1]

We will consider throttle handler and auth handler for this post. The sequences for handling these reside in [APIM_HOME]/repository/deployments/synapse-configs/default/sequences/ , as _auth_failure_handler_.xml and _throttle_out_handler_.xml

When an auth error occurs or when throttle limit is exceeded, APIM directs the flow to these handlers. We can set the desired fault payload in these handlers here by using a payload factory. Consider the following sample in _throttle_out_handler_ sequence

<?xml version="1.0" encoding="UTF-8"?><sequence xmlns="http://ws.apache.org/ns/synapse" name="_throttle_out_handler_">
    <property name="error_message_type" scope="default" action="set" value="application/json"/>
    <payloadFactory media-type="xml">
      <format>
         <error xmlns="">
            <status>$1</status>
            <message>$2</message>
         </error>
      </format>
      <args>
         <arg expression="$ctx:ERROR_CODE" evaluator="xml"></arg>
         <arg expression="$ctx:ERROR_MESSAGE" evaluator="xml"></arg>
      </args>
    <sequence key="_build_"/>
    <property name="X-JWT-Assertion" scope="transport" action="remove"/>
</sequence>
Payload factory mediator is used create the custom error message. This is not mandatory if you want the default error message.  

Consider the following property which is set to get the error message in application/json. Setting messageType property is not applicable to handlers, you need to set error_message_type for this.

<property name="error_message_type" scope="default" action="set" value="application/json"/>
Reference : 

December 11, 2015

JSON Payload as String in Mediation

Due to the underlying synapse engine based on SOAP/XML message format, when a JSON payload is to be processed with ESB, it is being built as a XML message by default. In any case if we want to use the JSON payload as a string in our mediation, we will need to follow the below steps.

First the payload needs to be set as a string property as below :
<property name="JSONPayload" expression="json-eval($.)"/>
This property can then be used for any transformations as a string literal of the JSON.

Check out the sample below, which gets the response from the <call> mediator as a JSON, saves it to a string and then uses it in an xml payload. The final response of the API is XML.
<api xmlns="http://ws.apache.org/ns/synapse" name="JSONTestAPI" context="/json">
   <resource methods="GET">
      <inSequence>
         <call>
            <endpoint key="MockBackend"></endpoint>
         </call>
         <property name="JSONPayload" expression="json-eval($.)"></property>
         <log level="full">
            <property name="====JSONPayload====" expression="$ctx:JSONPayload"></property>
         </log>
         <payloadFactory media-type="xml">
            <format>
               <xmlPayload xmlns="">
                  <jsonPayload>$1</jsonPayload>
               </xmlPayload>
            </format>
            <args>
               <arg evaluator="xml" expression="$ctx:JSONPayload"></arg>
            </args>
         </payloadFactory>
         <property name="messageType" value="application/xml" scope="axis2"></property>
         <respond></respond>
      </inSequence>
   </resource>
</api>


Response from mock backend is as below :
{
  "mock":"mock service"
}

JSON payload will be logged as below when invoking the API. Notice that although the JSON payload is built to XML, the property preserves the payload as a string literal.

LogMediator To: http://www.w3.org/2005/08/addressing/anonymous, WSAction: , SOAPAction: , MessageID: urn:uuid:08b4f213-0df0-4d18-88b7-8cf3e2d1872c, Direction: request, ====JSONPayload==== = {
   "mock":"mock service"
}, Envelope: <?xml version="1.0" encoding="utf-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><jsonObject><mock>mock service</mock></jsonObject></soapenv:Body></soapenv:Envelope>

Final response from the API is as below :
<xmlPayload>
      <jsonPayload>{"mock":"mock service"}</jsonPayload>
</xmlPayload>

Additional Reference : 
http://stackoverflow.com/questions/27848342/getpayloadjson-returning-an-empty-object