Scenario:
The API basically calls an endpoint to get the token and then sets the token in the header and calls another endpoint along with other query parameters.
Problem:
I'm getting the null resolving to address issue.
[2022-11-09 18:08:19,327] INFO {LogMediator} - {api:MsaasproEsb} To: http://www.w3.org/2005/08/addressing/anonymous, WSAction: , SOAPAction: , MessageID: urn:uuid:e763462f-c7dc-4f3d-a8ba-b23c5f66a241, correlation_id: 7dba4bab-4218-48ca-9871-e4c2d249a91b, Direction: request, Payload: {"Data": {"status": 200, "id": 190, "user_id": "secpapi", "email": "Faisal.furqan#secp.gov.pk", "token": "9704e4de2acde3af0686c22d409f831db3d1fd76"}}
[2022-11-09 18:08:19,328] INFO {TRACE_LOGGER} - Sending message through endpoint : null resolving to address = https://msaaspro.com/api/v1/scan/pep-scan/?fullname={uri.var.name}&searchtype=fuzzy&fathername={uri.var.fatherName}&dobyear={uri.var.dobYear}&cnic={uri.var.cnic}&mobile={uri.var.mobile}&country={uri.var.country}&name_similarity=90
[2022-11-09 18:08:19,328] INFO {TRACE_LOGGER} - SOAPAction:
[2022-11-09 18:08:19,328] INFO {TRACE_LOGGER} - WSA-Action:
[2022-11-09 18:09:17,775] INFO {SourceHandler} - Writer null when calling informWriterError
[2022-11-09 18:09:17,775] WARN {SourceHandler} - STATE_DESCRIPTION = Socket Timeout occurred after accepting the request headers and the request body, INTERNAL_STATE = REQUEST_DONE, DIRECTION = REQUEST, CAUSE_OF_ERROR = Connection between the client and the EI timeouts, HTTP_URL = /msaaspro/send, HTTP_METHOD = POST, SOCKET_TIMEOUT = 180000, CLIENT_ADDRESS = /127.0.0.1:55470, CONNECTION http-incoming-4 Correlation ID : 965986e6-2d6b-4108-aefe-3a7a648eb61a
[2022-11-09 18:10:44,079] INFO {SourceHandler} - Writer null when calling informWriterError
[2022-11-09 18:10:44,079] WARN {SourceHandler} - STATE_DESCRIPTION = Socket Timeout occurred after accepting the request headers and the request body, INTERNAL_STATE = REQUEST_DONE, DIRECTION = REQUEST, CAUSE_OF_ERROR = Connection between the client and the EI timeouts, HTTP_URL = /msaaspro/send, HTTP_METHOD = POST, SOCKET_TIMEOUT = 180000, CLIENT_ADDRESS = /127.0.0.1:58755, CONNECTION http-incoming-5 Correlation ID : 1fc72034-a9d1-46ad-9198-d18810065c10
[2022-11-09 18:11:19,011] INFO {SourceHandler} - Writer null when calling informWriterError
[2022-11-09 18:11:19,011] WARN {SourceHandler} - STATE_DESCRIPTION = Socket Timeout occurred after accepting the request headers and the request body, INTERNAL_STATE = REQUEST_DONE, DIRECTION = REQUEST, CAUSE_OF_ERROR = Connection between the client and the EI timeouts, HTTP_URL = /msaaspro/send, HTTP_METHOD = POST, SOCKET_TIMEOUT = 180000, CLIENT_ADDRESS = /127.0.0.1:58781, CONNECTION http-incoming-6 Correlation ID : 7dba4bab-4218-48ca-9871-e4c2d249a91b
Source code:
<?xml version="1.0" encoding="UTF-8"?>
<api context="/msaaspro" name="MsaasproEsb" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST" uri-template="/send">
<inSequence>
<property description="username" name="username" scope="default" type="STRING" value="json-eval($.username)"/>
<property description="password" name="password" scope="default" type="STRING" value="json-eval($.password)"/>
<call>
<endpoint>
<http method="post" statistics="enable" uri-template="https://msaaspro.com/api/v1/auth/auth-token/">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>-1</progressionFactor>
<maximumDuration>0</maximumDuration>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
<property description="token" name="token" scope="default" type="STRING" value="json-eval($.Data.token)"/>
<property description="Authorization" name="Authorization" scope="transport" type="STRING" value="fn:concat('Token ', get-property('token'))"/>
<property description="name" name="uri.var.name" scope="default" type="STRING" value="json-eval($.name)"/>
<property description="fatherName" name="uri.var.fatherName" scope="default" type="STRING" value="json-eval($.fatherName)"/>
<property description="dobYear" name="uri.var.dobYear" scope="default" type="STRING" value="json-eval($.dobYear)"/>
<property description="uniqueKey" name="uri.var.cnic" scope="default" type="STRING" value="json-eval($.cnic)"/>
<property description="country" name="uri.var.country" scope="default" type="STRING" value="json-eval($.country)"/>
<property description="mobile" name="uri.var.mobile" scope="default" type="STRING" value="json-eval($.mobile)"/>
<log level="full"/>
<call>
<endpoint>
<http method="get" statistics="enable" trace="enable" uri-template="https://msaaspro.com/api/v1/scan/pep-scan/?fullname={uri.var.name}&searchtype=fuzzy&fathername={uri.var.fatherName}&dobyear={uri.var.dobYear}&cnic={uri.var.cnic}&mobile={uri.var.mobile}&country={uri.var.country}&name_similarity=90">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>-1</progressionFactor>
<maximumDuration>0</maximumDuration>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
</inSequence>
<outSequence>
<respond/>
</outSequence>
<faultSequence/>
</resource>
</api>
Question:
My exact question is why I'm getting null resolving issue while I've set properties for all the parameters that I've passed to the endpoint. I'm able to call the first endpoint and I successfully get the token but somehow I'm unable to call the second endpoint.
In the property mediators, when you use XPath or JSONPath expressions, you need to use the expression parameter instead of value. For example,
<property description="token" name="token" scope="default" type="STRING" value="json-eval($.Data.token)"/>
should be updated as follows,
<property description="token" name="token" scope="default" type="STRING" expression="json-eval($.Data.token)"/>
Can you update all the property mediators as above and try them out?
I couldn't find a <respond/> mediator after the call mediator in your insequence. To send the response back to the client you need to have Respond Mediator.
Regarding the log message Sending message through endpoint : null resolving to address, since we have used an anonymous endpoint, the trace logger couldn't resolve a name for the endpoint. That's why it's printing a null in the trace log.
I'm not sure why you are seeing null in the Trace logs. But I assume that's the expected behavior with an HTTP Endpoint. I see a typo in your second URL. Check the following. After pep-scan you shouldn't have a / before the query params.
uri-template="https://msaaspro.com/api/v1/scan/pep-scan?fullname={uri.var.name}&searchtype=fuzzy&fathername={uri.var.fatherName}&dobyear={uri.var.dobYear}&cnic={uri.var.cnic}&mobile={uri.var.mobile}&country={uri.var.country}&name_similarity=90"
If that doesn't resolve the issue, try adding the following property before the second HTTP call.
<property action="remove" name="TRANSPORT_HEADERS" scope="axis2"/>
Add the above in the following order.
<property action="remove" name="TRANSPORT_HEADERS" scope="axis2"/>
<property description="token" name="token" scope="default" type="STRING" value="json-eval($.Data.token)"/>
<property description="Authorization" name="Authorization" scope="transport" type="STRING" value="fn:concat('Token ', get-property('token'))"/>
<property description="name" name="uri.var.name" scope="default" type="STRING" value="json-eval($.name)"/>
<property description="fatherName" name="uri.var.fatherName" scope="default" type="STRING" value="json-eval($.fatherName)"/>
<property description="dobYear" name="uri.var.dobYear" scope="default" type="STRING" value="json-eval($.dobYear)"/>
<property description="uniqueKey" name="uri.var.cnic" scope="default" type="STRING" value="json-eval($.cnic)"/>
<property description="country" name="uri.var.country" scope="default" type="STRING" value="json-eval($.country)"/>
<property description="mobile" name="uri.var.mobile" scope="default" type="STRING" value="json-eval($.mobile)"/>
<log level="full"/>
<call>
<endpoint>
<http method="get" statistics="enable" trace="enable" uri-template="https://msaaspro.com/api/v1/scan/pep-scan/?fullname={uri.var.name}&searchtype=fuzzy&fathername={uri.var.fatherName}&dobyear={uri.var.dobYear}&cnic={uri.var.cnic}&mobile={uri.var.mobile}&country={uri.var.country}&name_similarity=90">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>-1</progressionFactor>
<maximumDuration>0</maximumDuration>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
If you still see the issue, enable wire logs and compare the outgoing message with a direct request and try to find what's different.
Related
Scenario
I'm sending a request payload to the API that further calls the SMS service provider in the in-sequence flow, I need to share back the response from the SMS service provider as it is. The API works fine and I do receive SMS on phone but I'm unable to share back the response from the service provider in the out sequence flow.
The response body from my SMS service provider is actually text as shown:
The Response header of SMS Service Provider looks like this:
API
<?xml version="1.0" encoding="UTF-8"?>
<api context="/mobilink" name="MobilinkSmsApi" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST" uri-template="/send">
<inSequence>
<property action="remove" name="TRANSPORT_HEADERS" scope="axis2"/>
<property description="username" expression="json-eval($.username)" name="uri.var.username" scope="default" type="STRING"/>
<property description="password" expression="json-eval($.password)" name="uri.var.password" scope="default" type="STRING"/>
<property description="to" expression="json-eval($.to)" name="uri.var.to" scope="default" type="STRING"/>
<property description="from" expression="json-eval($.from)" name="uri.var.from" scope="default" type="STRING"/>
<property description="message" expression="json-eval($.message)" name="uri.var.message" scope="default" type="STRING"/>
<log level="full"/>
<call>
<endpoint>
<http method="post" statistics="enable" trace="enable" uri-template="https://coXXXXX.XXXX.com/sendsms_url.html?Username={uri.var.username}&Password={uri.var.password}&From={uri.var.from}&To={uri.var.to}&Message={uri.var.message}">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>-1</progressionFactor>
<maximumDuration>0</maximumDuration>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
</inSequence>
<outSequence>
<log category="TRACE" level="full"/>
<property description="Content-Type" name="Content-Type" scope="default" type="STRING" value="text/html"/>
<property name="messageType" scope="axis2" type="STRING" value="text/html"/>
<respond/>
</outSequence>
<faultSequence>
<log category="ERROR" level="full"/>
</faultSequence>
</resource>
</api>
Question
My Question is how to share back the response from the service provider in the out sequence? I tried to use property with value text/html and even used content-type as text/html but It didn't worked.
There are two ways to achieve this. either one of below mentioned way you can follow
place <respond/> after <call> mediator
Use <Send> mediator instead of <call>, so that flow will come from insequence to outsequence where you already placed <respond/> to send back message to client
The issue got resolved when I placed the mediator in the inSequence flow.
previously I was placing the mediator in the outSequence
I tired to send the request to an endpoint I get the AnonymousEndpoint error and when I hit the endpoint URL with request in the postman it's working fine what should I do to fix this issue.
And I even tired the markForSuspension and suspendOnFailure configuration nothing worked as excepted.
<property name="singleQuote" scope="default" type="STRING" value="'"/>
<property description="AppConfig" expression="evaluate(fn:concat('get-property(',get-property('singleQuote'),'QRSag_iAppraisal_Config_',get-property('clientOrg'),get-property('singleQuote'),')' ))" name="AppConfig" scope="default" type="OM"/>
<property expression="$ctx:AppConfig//*[local-name()='laravel_url']/text()" name="uri.var.apiurl" scope="default" type="STRING"/>
<property expression="$ctx:AppConfig//*[local-name()='authorization']/text()" name="Authorization" scope="transport" type="STRING"/>
<!--
<log level="custom">
<property name="uri.var.apiurl ::::::::::::::::::: " expression="$ctx:uri.var.apiurl"/>
<property name="Authorization ::::::::::::::::::: " expression="$trp:Authorization"/>
</log> -->
<call description="VB iAppraisal Endpoint">
<endpoint>
<http method="post" uri-template="{uri.var.apiurl}"/>
</endpoint>
</call>
<!-- <log level="custom">
<property name="Laravel API Response ::::::::::::::::::: " expression="json-eval($.)"/>
</log> -->
we are using WSo2 API Manager 2.1.0.
when configuring an API in API Publisher we wanted to add a sequence of calls before calling the target API. So we added the In Sequence flow, where in a call Mediator we calling a REST API which return the values in response headers and a empty JSON Payload as 200.
In WSO2 API Manager we are getting the below response.
<am:fault xmlns:am="http://wso2.org/apimanager">
<am:code>401001</am:code>
<am:type>Status report</am:type>
<am:message>Runtime Error</am:message>
<am:description>Payload is not a JSON string.</am:description> </am:fault>
<header name="Content-Type" scope="transport" value="application/json"/>
<property name="messageType" scope="transport" type="STRING" value="application/json"/>
<log level="full"/>
<header name="site_id" scope="transport" value="004ada8a-6a11-f080-f56c-12dd3808e8f7"/>
<header expression="fn:concat('Bearer ', get-property('generated-access-token'))" name="Authorization" scope="transport" xmlns:ns3="http://org.apache.synapse/xsd" xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"/>
<call blocking="true">
<endpoint>
<http method="put" uri-template="https://wso2.domainname.com/api/v1.0/users/me/login-defaults">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>1</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
<log level="full"/>
<property description="session-id" expression="$trp:X-NG-SessionId" name="session-id" scope="default" type="STRING"/>
<log level="custom">
<property expression="$trp:X-NG-SessionId" name="Access Token after call if block"/>
</log>
<property expression="$ctx:resource" name="REST_URL_POSTFIX" scope="axis2" type="STRING"/>
I am using WSO2 Integrator 6.6.0 to make a blocking HTTP GET to a REST API that returns a JSON response (HTTP 200 OK).
But I never see the response body inside my sequences. I am not sure what I am doing wrong, having exhausted all available documentation and other threads.
Sequence doing the call (simplified to anonymize), which logs the response afterwards:
<!-- Remove XML body as not needed for GET request -->
<payloadFactory media-type="json">
<format></format>
<args></args>
</payloadFactory>
<header name="Accept" value="application/json" scope="transport"/>
<property name="NO_ENTITY_BODY" value="true" scope="axis2" type="BOOLEAN" />
<call blocking="true">
<endpoint>
<http method="GET" uri-template="http://my-api/order-status">
</endpoint>
</call>
<property name="RESPONSE" scope="default" type="STRING" value="true"/>
<log level="full">
<property name="response-log" value="Received response"/>
<property expression="$body" name="response-body"/>
<property expression="json-eval($)" name="json-eval-body"/>
</log>
This results simply into a log line - with no response body at all!
INFO {org.apache.synapse.mediators.builtin.LogMediator} - To:
http://my-api/order-status, WSAction: urn:mediate, SOAPAction:
urn:mediate, MessageID:
ID:414d51204343494153303131202020209ca4175f28ac422e, Direction:
response, response-log = Received response, response-body =
<soapenv:Body
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"></soapenv:Body>,
json-eval-body = {}, Payload: {}
I can see the request in my API application and I can also see what it correctly returns a response body in its logs. Also, using Postman to do the same request I receive the following JSON response with 200 OK and Content-Type appication/json:
{
"order_status": "NOT_FOUND"
}
Inside WSO2 I do not see anything! I want to be able to convert the response into XML format.
What could be wrong?
Before making a REST call, it is necessary to remove the headers from the main call.
Put this snippet before the call mediator:
<property name = "FORCE_HTTP_CONTENT_LENGTH" scope = "axis2" type = "STRING" value = "true" />
<property action = "remove" name = "REST_URL_POSTFIX" scope = "axis2" />
<property action = "remove" name = "TRANSPORT_HEADERS" scope = "axis2" />
As I understand it should solve.
Can you modify the NO_ENTITY_BODY property as follows and try this mediation again.
<property name="NO_ENTITY_BODY" action="remove" scope="axis2"/>
Having simplified this configuration for this question, I had missed that having the following property set in my proxy service:
<property name="OUT_ONLY" scope="default" type="STRING" value="true"/>
Means that WSO2 is ignoring the response from the API. Removing this property resolved the issue for the following config:
<header name="Accept" value="application/json" scope="transport" />
<property action="remove" name="NO_ENTITY_BODY" scope="axis2"/>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<call blocking="true">
<endpoint key="conf:/endpoints/FX_TRADING_API_ORDERSTATUS.xml"/>
</call>
I am working on the WSO2 ESB Proxy service, which involves exposing the internal RESTful service via SOAP endpoint on the ESB.
My RESTful service requires Content-type = "application/rdf+xml". I tried setting it using all 3 properties mentioned in the documentation: messageType, ContentType and CONTENT_TYPE. However, the request Content-type still remains "application/xml".
Here is an excerpt from my sequence that calls REST service:
<property xmlns:ns="http://org.apache.synapse/xsd" name="REST_URL_POSTFIX" value="/record/12345" scope="axis2" type="STRING"/>
<property name="HTTP_METHOD" value="PUT" scope="axis2" type="STRING"/>
<property name="messageType" value="application/rdf+xml" scope="axis2" type="STRING"/>
<property name="ContentType" value="application/rdf+xml" scope="axis2" type="STRING"/>
<property name="CONTENT_TYPE" value="application/rdf+xml" scope="axis2" type="STRING"/>
<send>
<endpoint name="CQ">
<address uri="http://my_url" format="pox">
</address>
<property xmlns:ns="http://org.apache.synapse/xsd" name="Authorization" expression="fn:concat('Basic ', base64Encode('username:password'))" scope="transport"/>
<property name="OSLC-Core-Version" value="2.0" scope="transport"/>
<property name="Accept" value="application/rdf+xml" scope="transport"/>
</endpoint>
</send>
I tested it with TCPMon and no matter what Content-type property I use, request still contains "application/xml".
Please advice.
Can you try WSO2 ESB 4.7.0 with following configuration? Note that, I have changed the address format from "pox" to "rest"
<property xmlns:ns="http://org.apache.synapse/xsd" name="REST_URL_POSTFIX" value="/record/12345" scope="axis2" type="STRING"/>
<property name="HTTP_METHOD" value="PUT" scope="axis2" type="STRING"/>
<property name="messageType" value="application/rdf+xml" scope="axis2" type="STRING"/>
<property name="ContentType" value="application/rdf+xml" scope="axis2" type="STRING"/>
<property name="CONTENT_TYPE" value="application/rdf+xml" scope="axis2" type="STRING"/>
<send>
<endpoint name="CQ">
<address uri="http://my_url" format="rest">
</address>
<property xmlns:ns="http://org.apache.synapse/xsd" name="Authorization" expression="fn:concat('Basic ', base64Encode('username:password'))" scope="transport"/>
<property name="OSLC-Core-Version" value="2.0" scope="transport"/>
<property name="Accept" value="application/rdf+xml" scope="transport"/>
</endpoint>
</send>
These are the http headers sent now (captured from tcpmon)
PUT /record/12345 HTTP/1.1
Cookie: region1_configure_menu=none; region3_registry_menu=none; region4_monitor_menu=none; region5_tools_menu=none; JSESSIONID=54D2911FCD5559C6B2F723E7C6FA9B44; requestedURI="../../carbon/service-mgt/index.jsp?region=region1&item=services_list_menu"; current-breadcrumb=manage_menu%2Cservices_menu%2Cservices_list_menu%23
Authorization: null
OSLC-Core-Version: 2.0
Content-Type: application/rdf+xml
Accept: application/rdf+xml
Transfer-Encoding: chunked
Host: www.foo.com:8080
Connection: Keep-Alive
User-Agent: Synapse-PT-HttpComponents-NIO
In the configuration you have attached, you have specified the format of the address uri as "pox" .
<address uri="http://my_url" format="pox">
This will be the reason that you are getting content-type as application/xml always. Please remove this attribute and try. It should be
<address uri="http://my_url">
If you still see the issue, then try to switch to the NHTTP transport as suggested by RaviU. For that, you can first backup the axis2.xml (ESB_HOME/repository/conf/axis2/axis2.xml) as axis2_back.xml and then rename the axis2_nhttp.xml file (same location) as axis2.xml.
Can you set the content type property like this;
<property name="Content-Type” value="application/rdf+xml" scope="transport"/>
Please remove other content-type properties..
If you define like this;
[1]<property name="messageType" value="application/rdf+xml" scope="axis2" type="STRING"/>
[2]<property name="ContentType" value="application/rdf+xml" scope="axis2" type="STRING"/>
[1] for, to select messageformatter
[2]for, to select message builders
Edit;
try like this
<inSequence>
<log level="custom">
<property name="in seq --------------of proxy" expression="$trp:Content-Type"/>
</log>
<property name="messageType"
value="application/json"
scope="axis2"
type="STRING"/>
<property name="Content-Type"
value="application/json"
scope="transport"
type="STRING"/>
<log level="custom">
<property name="in seq --------------of proxy" expression="$trp:Content-Type"/>
</log>
<send>
<endpoint>
<address uri="http://localhost:5555/com"/>
</endpoint>
</send>
Sometimes, you have to enable those message formatters in axis2.xml before using them.
Check this article out. It may help if you haven't done so yet.
http://wso2.com/library/articles/axis2-configuration-part2-learning-axis2-xml#mf