I want to Send SMS twilio by postman through Wso2 ESB , the body , to and from parameters submitted through postman to wso2 sequence , I'm trying to do it by payloadFactory but it does not work , it said :
<TwilioResponse>
<RestException>
<Code>21602</Code>
<Message>Message body is required.</Message>
<MoreInfo>https://www.twilio.com/docs/errors/21602</MoreInfo>
<Status>400</Status>
</RestException>
I'm using https://api.twilio.com/2010-04-01/Accounts/AC*****************/Messages
as endpoint to send it to Twilio
my sequence :
<property expression="json-eval($.Body)" name="Body" scope="default"
type="STRING" xmlns:ns="http://org.apache.synapse/xsd"/>
<property expression="json-eval($.To)" name="To" scope="default"
type="STRING" xmlns:ns="http://org.apache.synapse/xsd"/>
<property expression="json-eval($.From)" name="From" scope="default"
type="STRING" xmlns:ns="http://org.apache.synapse/xsd"/>
<payloadFactory media-type="json">
<format> { "Body": $1, "From": $2 ,"To": $3 } </format>
<args>
<arg evaluator="xml" expression="get-property('Body')"
literal="false" xmlns:ns="http://org.apache.synapse/xsd"/>
<arg evaluator="xml" expression="get-property('From')"
literal="false" xmlns:ns="http://org.apache.synapse/xsd"/>
<arg evaluator="xml" expression="get-property('To')"
literal="false" xmlns:ns="http://org.apache.synapse/xsd"/>
</args>
</payloadFactory>
<call>
<endpoint key="twill2"/>
</call>
<send/>
and my postman request :
{
"Body":"hi dear",
"To":"+(***) *******",
"From":"+1 *******"
}
We have observed that in some cases even though the body is present in the request endpoints returning this error. This is due to the additional headers present or absence of some headers. Can you please try adding the following properties prior to the endpoint call
<property action="remove" name="TRANSPORT_HEADERS" scope="axis2"/>
<property name="setCharacterEncoding" scope="axis2" value="false"/>
<property name="DISABLE_CHUNKING" scope="axis2" value="true"/>
<property name="ContentType" scope="axis2" value="application/json"/>
You can refer to the documentation 1, [2], [3], [4] for additional details on the above properties.
1-https://docs.wso2.com/display/EI660/Generic+Properties#GenericProperties-TRANSPORT_HEADERS
[2]-https://docs.wso2.com/display/EI6xx/Axis2+Properties#Axis2Properties-setCharacterEncoding
[3]-https://docs.wso2.com/display/EI660/HTTP+Transport+Properties#HTTPTransportProperties-DISABLE_CHUNKINGDISABLE_CHUNKING
[4]-https://docs.wso2.com/display/EI660/Generic+Properties#GenericProperties-ContentType
Updated
Can you enable wire in ESB server and attach logs when you invoke the endpoint directly. Refer to the blog [5] on enabling wire logs. Also please attach the curl command of the postman request. You can obtain this by selecting the code button in postman and selecting curl.
[5]-http://lakshanigamage.blogspot.com/2015/03/how-to-enable-wire-logs-in-wso2-esbapim.html
Related
I'm retrieving some data's from DSS by using select query and then some transformation by payload factory after that I'm passing it to an endpoint, but when I do that the empty fields are being passed as null and not as empty strings ""
"department":"{department":null}",
"Selling_dealer__c":"{Selling_dealer__c":null}"
I wish it really showed like this:
"department":"",
"Selling_dealer__c":""
Note: Also tried the synapse properties file method but not working as excepted refer link 1 refer link 2
<sequence name="LaravelConnectorSequence" xmlns="http://ws.apache.org/ns/synapse">
<payloadFactory media-type="json">
<format>
{
"screen_type": "opportunity",
"vehicle_type__c": "",
"description": "",
"audio_file_name__c": "$1",
"lead_type__c": "Phone",
"request_type__c": "",
"mobile__c": "$2",
"leadsource": "Novum",
"company__c": "N/A",
"location__c": "$3",
"department__c": "$4",
"selling_dealer__c":"$5"
}
</format>
<args>
<arg evaluator="xml"
expression="get-property('audioFileName')"
literal="false" xmlns:ns="http://org.apache.synapse/xsd"/>
<arg evaluator="xml" expression="get-property('mobile')"
literal="false" xmlns:ns="http://org.apache.synapse/xsd"/>
<arg evaluator="xml" expression="get-property('location')"
literal="false" xmlns:ns="http://org.apache.synapse/xsd"/>
<arg evaluator="xml" expression="get-property('department')"
literal="false" xmlns:ns="http://org.apache.synapse/xsd"/>
<arg evaluator="xml"
expression="get-property('selling_dealer__c')"
literal="false" xmlns:ns="http://org.apache.synapse/xsd"/>
</args>
</payloadFactory>
<log level="custom">
<property expression="json-eval($)"
name="=======Laravel Request====" xmlns:ns="http://org.apache.synapse/xsd"/>
</log>
<property expression="get-property('Novum-configs')" name="config"
scope="axis2" type="OM" xmlns:ns="http://org.apache.synapse/xsd"/>
<property expression="$axis2:config//*[local-name()='laravelToken']"
name="Authorization" scope="transport" type="STRING" xmlns:ns="http://org.apache.synapse/xsd"/>
<property expression="$axis2:config//*[local-name()='laravelURL']"
name="uri.var.laravelapi" scope="default" type="STRING" xmlns:ns="http://org.apache.synapse/xsd"/>
<call>
<endpoint>
<http method="POST" uri-template="{uri.var.laravelapi}"/>
</endpoint>
</call>
<log level="custom">
<property expression="json-eval($)"
name="=======Laravel Response====" xmlns:ns="http://org.apache.synapse/xsd"/>
</log>
Since you want to convert your null values into "" strings, one workaround would be to convert the JSON to XML and then extract the elements from that and add them to your final JSON payload. In WSO2 there are different options you can set when converting JSON payloads. You can read about different options and how to work with JSON messages from here.
Since you want null to be "". You need to set the following property. If you are on MI this needs to go into deployment.toml, if on EI this goes into synapse.properties
'synapse.commons.enableXmlNullForEmptyElement'=false
Note: In MI (Surround the property name with single quotes)
When you are extracting data from the DSS response make sure to use Xpath expressions instead of JSON path expressions. Following is a simplified version of your configurations. Note I have hardcoded the DSS response.
<?xml version="1.0" encoding="UTF-8"?>
<api context="/api" name="RESTApi" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="GET" url-mapping="/sample">
<inSequence>
<payloadFactory media-type="json">
<format>{"Selling_dealer__c": null}</format>
<args/>
</payloadFactory>
<property expression="//Selling_dealer__c" name="logInJson" scope="default" type="STRING"/>
<payloadFactory media-type="json">
<format>
{
"screen_type": "opportunity",
"selling_dealer__c": "$1"
}
</format>
<args>
<arg evaluator="xml" expression="$ctx:logInJson"/>
</args>
</payloadFactory>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
Above will produce the following response.
{
"screen_type": "opportunity",
"selling_dealer__c": "{"Selling_dealer__c":""}"
}
I used the script mediator to overcome this issue.
<script language="js"><![CDATA[var log=mc.getServiceLog();
var dep = mc.getProperty('department').toString();
var sell = mc.getProperty('selling_dealer__c').toString();
//log.info("===DepartmentValue===: "+dep);
var deps = mc.getProperty('department').startsWith("<Department");
//log.info("++++++++++++++++++++TRUE VALUE++++++++++++++++++"+deps);
if(dep.startsWith("<Department"))
{
dep ="";
mc.setProperty('department',dep);
}
//log.info("===DepartmentValueAfter===: "+dep)
//log.info("===SellingDealerValue===: "+sell);
var sells = mc.getProperty('selling_dealer__c').startsWith("<selling_dealer__c");
//log.info("++++++++++++++++++++TRUE VALUE++++++++++++++++++"+sells);
if(sell.startsWith("<selling_dealer__c"))
{
sell ="";
mc.setProperty('selling_dealer__c',sell);
}
//log.info("===selling_dealer__cValueAfter===: "+sell)
]]></script>
How can i get the endpoint production or sandbox url in customsequence?
Or how can i use two payload factories in the same customsequence using the endpoint saved in the api manager publisher?
For example, i have a custom sequence that made a call in the same endpoint, returning different data:
<payloadFactory description="" media-type="xml">
<format>
<ser:users xmlns:ser="http://service.test.com">
<arg0 xmlns="">$1</arg0>
</ser:users>
</format>
<args>
<arg value="user" />
</args>
</payloadFactory>
<call blocking="true">
<endpoint>
<address format="soap11" uri="http://url_soap?wsdl"/>
</endpoint>
</call>
<property expression="//return/text()" name="token" scope="default" type="STRING" xmlns:x="http://ws.wso2.org/dataservice"/>
Thanks
printscreen urls
I have created a REST API using WSO2 API Manager (StockQuoteService) and configured a back end SOAP based web service (converting REST to SOAP) from where it will be getting the data based on the URL template.
In the "In Sequence", I have used a Switch mediator to send the request to different back end endpoints based on incoming data whereas in the default scenario (when no case match), I want to send the error message back to the client that the "Input message is invalid".
I have tried using the Send mediator, Respond Mediator, Sequence Mediator but still no success (may be doing something wrong) as still I am getting "no response from server" error when I try to invoke the URL which doesn't match any case of Switch and goes to Default.
How can I send the Error/Fault message back to the client from In Sequence of WSO2 API Manager?
In my scenario, the input sequence I used the switch mediator and I invoke an operation or another, in the default option I create my failure response
<inSequence>
<switch xmlns:xsd="http://pharmacy.arce.org/xsd"
description=""
source="//xsd:desc">
<case regex="NATURAL">
<log description="Search Pharmacy" level="custom" separator=",">
<property name="STATUS" value="Search Pharmacy"/>
</log>
<payloadFactory media-type="xml">
<format>
<p:searchpharmacy xmlns:p="http://pharmacy.arce.org">
<ax22:pharmacy xmlns:ax22="http://pharmacy.arce.org">
<xs:desc xmlns:xs="http://pharmacy.arce.org/xsd">$1</xs:desc>
<xs:id xmlns:xs="http://pharmacy.arce.org/xsd">$2</xs:id>
<xs:latitude xmlns:xs="http://pharmacy.arce.org/xsd">$3</xs:latitude>
<xs:longitude xmlns:xs="http://pharmacy.arce.org/xsd">$4</xs:longitude>
</ax22:pharmacy>
</p:searchpharmacy>
</format>
<args>
<arg evaluator="xml" expression="//xsd:desc"/>
<arg evaluator="xml" expression="//xsd:id"/>
<arg evaluator="xml" expression="//xsd:latitude"/>
<arg evaluator="xml" expression="//xsd:longitude"/>
</args>
</payloadFactory>
<header name="To" scope="default" value="urn:searchpharmacy"/>
<log level="full" separator=",">
<property name="Mensaje" value="Cuerpo"/>
</log>
</case>
<case regex="EXPERIMENTAL">
<log description="Search Pharmacy Direction" level="custom" separator=",">
<property name="STATUS" value="Search Pharmacy Direction Request"/>
</log>
<payloadFactory media-type="xml">
<format>
<p:searchPhone xmlns:p="http://pharmacy.arce.org">
<ax22:pharmacy xmlns:ax22="http://pharmacy.arce.org">
<xs:desc xmlns:xs="http://pharmacy.arce.org/xsd">$1</xs:desc>
<xs:id xmlns:xs="http://pharmacy.arce.org/xsd">$2</xs:id>
<xs:latitude xmlns:xs="http://pharmacy.arce.org/xsd">$3</xs:latitude>
<xs:longitude xmlns:xs="http://pharmacy.arce.org/xsd">$4</xs:longitude>
</ax22:pharmacy>
</p:searchPhone>
</format>
<args>
<arg evaluator="xml" expression="//xsd:desc"/>
<arg evaluator="xml" expression="//xsd:id"/>
<arg evaluator="xml" expression="//xsd:latitude"/>
<arg evaluator="xml" expression="//xsd:longitude"/>
</args>
</payloadFactory>
<header name="Action" scope="default" value="urn:searchPhone"/>
<property name="SOAPAction" scope="transport" type="STRING" value=""/>
<log level="full" separator=",">
<property name="Data" value="Body"/>
</log>
</case>
<default>
<log description="Fault" level="custom" separator=",">
<property name="STATUS" value="Invoke fault "/>
</log>
<payloadFactory media-type="xml">
<format>
<rs:fault xmlns:rs="http://pharmacy.arce.org">
<rs:code>-1</rs:code>
<rs:type>Invocation error</rs:type>
<rs:message>No operation has been invoked</rs:message>
<rs:description>The value of the input parameter is not valid</rs:description>
</rs:fault>
</format>
<args/>
</payloadFactory>
<respond/>
</default>
</switch>
</inSequence>
Here is the default section
<default>
<log description="Fault" level="custom" separator=",">
<property name="STATUS" value="Invoke fault "/>
</log>
<payloadFactory media-type="xml">
<format>
<rs:fault xmlns:rs="http://pharmacy.arce.org">
<rs:code>-1</rs:code>
<rs:type>Invocation error</rs:type>
<rs:message>No operation has been invoked</rs:message>
<rs:description>The value of the input parameter is not valid</rs:description>
</rs:fault>
</format>
<args/>
</payloadFactory>
<respond/>
</default>
And the fault response
{"fault":{"code":-1,"type":"Invocation error","message":"No operation has been invoked","description":"The value of the input parameter is not valid"}}
You can find other scenarios here
http://harshcreationz.blogspot.com/2016/02/common-and-error-handling-sequences.html
This should work.
<payloadFactory media-type="json">
<format>
{
"error":"true",
"message":"error case"
}
</format>
</payloadFactory>
<property name="messageType" value="application/json" scope="axis2"/>
<respond/>
Nits
The error response as comments "no response from server", I receive it when I call the api from the test console that has the API Manager.
You can see this link
API Console Issue
To validate the response you expect.
Try calling from another tool such as SOAP UI or Postman, in my case I receive a fault response message with the structure defined.
This is the call from the console API
curl -X GET --header 'Accept: application/xml' --header 'Authorization: Bearer 465f1385-a120-3c19-ad22-c3057e744a3b' 'https://169.254.193.10:8252/getById/1.0.0/getEmployeeXML?Id=5'
For the call from another client in the header pass these values you have in the api call
Accept: application/json
Authorization: Bearer 465f1385-a120-3c19-ad22-c3057e744a3b'
We are using WSO2 IS 5.0.0 / API Manager 1.9.1. We created a Rest API to handle the call for the internal WSO2 soap call setChallengeQuestionsOfUser in the UserIdentityManagementAdminService, however when we call this method with a specific userName the method will always update the Admin account.
Here is a code we are using to invoke the soap service
<resource methods="POST" url-mapping="/updatechallengequestionofuser" faultSequence="fault"> <!-- Only Updating admin -->
<inSequence>
<class name="org.wso2.carbon.apimgt.gateway.mediators.TokenPasser"/>
<property name="USERNAME" expression="//userName" scope="default" type="STRING"/>
<property name="USERANSWER1" expression="//userAnswer1" scope="default" type="STRING"/>
<property name="QUESTIONSETID1" expression="//questionSetId1" scope="default" type="STRING"/>
<property name="QUESTIONTEXT1" expression="//questionText1" scope="default" type="STRING"/>
<property name="USERANSWER2" expression="//userAnswer2" scope="default" type="STRING"/>
<property name="QUESTIONSETID2" expression="//questionSetId2" scope="default" type="STRING"/>
<property name="QUESTIONTEXT2" expression="//questionText2" scope="default" type="STRING"/>
<property name="USERANSWER3" expression="//userAnswer3" scope="default" type="STRING"/>
<property name="QUESTIONSETID3" expression="//questionSetId3" scope="default" type="STRING"/>
<property name="QUESTIONTEXT3" expression="//questionText3" scope="default" type="STRING"/>
<payloadFactory media-type="xml">
<format>
<ser:setChallengeQuestionsOfUser xmlns:ser="http://services.mgt.identity.carbon.wso2.org" xmlns:xsd="http://dto.mgt.identity.carbon.wso2.org/xsd">
<ser:userName>$1</ser:userName>
<ser:challengesDTOs>
<xsd:answer>$2</xsd:answer>
<xsd:id>$3</xsd:id>
<xsd:question>$4</xsd:question>
</ser:challengesDTOs>
<ser:challengesDTOs>
<xsd:answer>$5</xsd:answer>
<xsd:id>$6</xsd:id>
<xsd:question>$7</xsd:question>
</ser:challengesDTOs>
<ser:challengesDTOs>
<xsd:answer>$8</xsd:answer>
<xsd:id>$9</xsd:id>
<xsd:question>$10</xsd:question>
</ser:challengesDTOs>
</ser:setChallengeQuestionsOfUser>
</format>
<args>
<arg evaluator="xml" expression="get-property('USERNAME')"/>
<arg evaluator="xml" expression="get-property('USERANSWER1')"/>
<arg evaluator="xml" expression="get-property('QUESTIONSETID1')"/>
<arg evaluator="xml" expression="get-property('QUESTIONTEXT1')"/>
<arg evaluator="xml" expression="get-property('USERANSWER2')"/>
<arg evaluator="xml" expression="get-property('QUESTIONSETID2')"/>
<arg evaluator="xml" expression="get-property('QUESTIONTEXT2')"/>
<arg evaluator="xml" expression="get-property('USERANSWER3')"/>
<arg evaluator="xml" expression="get-property('QUESTIONSETID3')"/>
<arg evaluator="xml" expression="get-property('QUESTIONTEXT3')"/>
</args>
</payloadFactory>
<header name="Action" scope="default" value="urn:setChallengeQuestionsOfUser"/>
<property name="Authorization" expression="fn:concat('Basic ', '<base64String>')" scope="transport"/>
<property name="Accept" expression="text/xml" scope="transport"/>
<property name="ContentType" value="text/xml" scope="axis2"></property>
<property name="messageType" value="text/xml" scope="axis2"></property>
<send>
<endpoint name="UserManagement_APIproductionEndpoint_4">
<address uri="https://wso2dev.comp.org/services/UserIdentityManagementAdminService" format="soap11">
</address>
</endpoint>
</send>
</inSequence>
<outSequence>
<class name="org.wso2.carbon.apimgt.usage.publisher.APIMgtResponseHandler"/>
<property name="ContentType" value="application/json" scope="axis2"></property>
<property name="messageType" value="application/json" scope="axis2"></property>
<send/>
</outSequence>
</resource>
There are no error messages in the wso2carbon.log file but we see that only the account named "admin" is getting updated. We can clear the challengeQuestion fields and run the Rest call again with a valid userName and see it fill out the questions for the admin account again.
This looks to be an issue with the underlying soap call setChallengeQuestionsOfUser. Has anyone identified a way to update the challenge questions for specific users?
If we are going to change the challenge questions of user1, then user1 should be authenticated to call this method.
However in IS 5.1.0 alpha2, users who are having permission "/permission/admin/configure/security" can change other users' challenge questions too.
Isura
I'm using wso2dss3.1.0 and wso2esb 4.7.0.
I wish to filter the condition for that I have user filter mediator.
My proxy is like :
<filter xpath="get-property('mailid1')=''">
<then>
<log level="custom">
<property name="service called" value="then of inner filter"/>
<property name="mailid exist" value="creating new entry in muser with phonenumber as username"/>
</log>
<payloadFactory>
<format>
<p:Capp_insert_emercontactid xmlns:p="http://ws.wso2.org/dataservice">
<p:username>$1</p:username>
<p:firstname>$2</p:firstname>
<p:lastname>$3</p:lastname>
<p:phonenumber>$4</p:phonenumber>
<p:mailid>$5</p:mailid>
</p:Capp_insert_emercontactid>
</format>
<args>
<arg expression="get-property('phoneno1')" evaluator="xml"/>
<arg expression="get-property('firstname')" evaluator="xml"/>
<arg expression="get-property('lastname')" evaluator="xml"/>
<arg expression="get-property('phoneno1')" evaluator="xml"/>
<arg expression="get-property('mailid1')" evaluator="xml"/>
</args>
</payloadFactory>
<property name="HTTP_METHOD" value="POST" scope="axis2" type="STRING"/>
<property name="RESPONSE" value="true" scope="default" type="STRING"/>
<property name="NO_ENTITY_BODY" action="remove" scope="axis2"/>
<log level="full"/>
<send receive="UpdateEmergencyContact_seq3">
<endpoint>
<address uri="http://localhost:9764/services/Capp_MuserDataservice/" format="soap11"/>
</endpoint>
</send>
</then>
<else>
<log level="custom">
<property name="service called" value="else of inner filter"/>
<property name="Phonenumber exist" value="creating new entry in muser with mailid as username"/>
</log>
<payloadFactory>
<format>
<p:Capp_insert_emercontactid xmlns:p="http://ws.wso2.org/dataservice">
<p:username>$1</p:username>
<p:firstname>$2</p:firstname>
<p:lastname>$3</p:lastname>
<p:phonenumber>$4</p:phonenumber>
<p:mailid>$5</p:mailid>
</p:Capp_insert_emercontactid>
</format>
<args>
<arg expression="get-property('mailid1')" evaluator="xml"/>
<arg expression="get-property('firstname')" evaluator="xml"/>
<arg expression="get-property('lastname')" evaluator="xml"/>
<arg expression="get-property('phoneno1')" evaluator="xml"/>
<arg expression="get-property('mailid1')" evaluator="xml"/>
</args>
</payloadFactory>
<property name="HTTP_METHOD" value="POST" scope="axis2" type="STRING"/>
<property name="RESPONSE" value="true" scope="default" type="STRING"/>
<property name="NO_ENTITY_BODY" action="remove" scope="axis2"/>
<log level="full"/>
<send receive="UpdateEmergencyContact_seq3">
<endpoint>
<address uri="http://localhost:9764/services/Capp_MuserDataservice/" format="soap11"/>
</endpoint>
</send>
</else>
</filter>
I wish to do:
If mailid and phonenumber present in request then insert mailid as
username.
If only mailid present insert it as username.
if mailid absent insert phonenumber as username.
and configuration I have written is eorkinh fine for else part.
When mailid present proxy allow to insert it as username.
But problem occurred while mailid absent.In this case it sends blank username.. Even not accept hardcoded value.
Log for above at server side is like:
[2014-06-25 10:29:29,676] INFO - LogMediator phoneno1 = 111, mailid1 =
[2014-06-25 10:29:29,677] INFO - LogMediator service called = else of inner filter, Phonenumber exist = creating new entry in muser with mailid as username
[2014-06-25 10:29:29,681] INFO - LogMediator To: http://www.w3.org/2005/08/addressing/anonymous, WSAction: , SOAPAction: , MessageID: urn:uuid:f7e63fab-168c-4364-b49b-6c68d6e84eff, Direction: response, Envelope: <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><p:Capp_insert_emercontactid xmlns:p="http://ws.wso2.org/dataservice"><p:username> </p:username><p:firstname>y1</p:firstname><p:lastname>y2</p:lastname><p:phonenumber/><p:mailid> </p:mailid></p:Capp_insert_emercontactid></soapenv:Body></soapenv:Envelope>
[2014-06-25 10:29:29,723] INFO - LogMediator service called = UpdateEmergencyContact_seq3, userid exist = updating appusers emergency contact with newly insert userid, userid of new entry = 391529635516515404
Where is exact problem?
Am I missing something or doing some wrong while writing filter?
Please let me know soon.
it is simple error ..In your else condition . you are passing mail id as username..So, if mailid is not there, username also empty. Check your payload fcatory argument expression
in your filter xpath use boolean(get-property('mailid1')) and compare it with true and false.