Why WSO2 API Manger can't execute PUT request when Mediation Policies is exist? - wso2

I have mediation settings for request and response:
for request(jms_in_flow):
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="jms_in_flow" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<property name="transactionId" expression="get-property('MessageID')"/>
<clone continueParent="true">
<target>
<sequence>
<property action="remove" name="OUT_ONLY" value="true"/>
<property expression="$ctx:api.ut.api_version" name="api_version" scope="transport" type="STRING"/>
<property expression="$ctx:api.ut.version" name="api_short_version" scope="transport" type="STRING"/>
<property expression="$ctx:api.ut.requestTime" name="api_request_time" scope="transport" type="STRING"/>
<property expression="$ctx:REST_API_CONTEXT" name="api_context" scope="transport" type="STRING"/>
<property expression="$ctx:API_NAME" name="api_name" scope="transport" type="STRING"/>
<property name="api_message_id" expression="get-property('transactionId')" scope="transport"/>
<property value="REQUEST" name="api_message_type" scope="transport" type="STRING"/>
<property expression="$ctx:REST_FULL_REQUEST_PATH" name="api_request_path" scope="transport" type="STRING"/>
<property expression="$ctx:api.ut.HTTP_METHOD" name="api_method" scope="transport" type="STRING"/>
<property expression="$ctx:api.ut.application.name" name="api_app_name" scope="transport" type="STRING"/>
<property expression="$ctx:api.ut.userName" name="api_username" scope="transport" type="STRING"/>
<call>
<endpoint>
<address uri="jms:"AAA"/>
</endpoint>
</call>
<drop/>
<send/>
</sequence>
</target>
</clone>
for response(jms_out_flow):
<sequence name="jms_out_flow" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<clone continueParent="true">
<target>
<sequence>
<property name="RESPONSE" value="true"/>
<property name = "api_response_time" expression = "get-property('SYSTEM_TIME')" scope="transport"/>
<property name="api_message_id" expression="get-property('transactionId')" scope="transport"/>
<property value="RESPONSE" name="api_message_type" scope="transport" type="STRING"/>
<property expression="$axis2:HTTP_SC" name="http_status" scope="transport" type="STRING"/>
<call>
<endpoint>
<address uri="jms:/AAA"/>
</endpoint>
</call>
<drop/>
</sequence>
</target>
</clone>
When I execute GET request on WSO2 Manager it executes fast and successful, and PUT request is not execute and falls off after the time expires(~2min). When I remove the mediator settings for the request (jms_in_flow), PUT request starts working normally.
I think that the error is in jms_in_flow, but I can't find it.
I found in google: Enter link description here
The processing of get and put methods is different, but I don’t know how to apply it.
UPDATE.
LOGS
[2019-07-01 13:38:06,083] ERROR - Unexpected error during sending message out {org.apache.synapse.core.axis2.Axis2Sender}
org.apache.axis2.AxisFault: Did not receive a JMS response within 30000 ms to destination : temp-queue://ID:c115c33d0c81-45342-543:1:1 with JMS correlation ID : ID:c115c33d0c81-45342-543:1:1:1:1
at org.apache.axis2.transport.base.AbstractTransportSender.handleException(AbstractTransportSender.java:234)
at org.apache.axis2.transport.jms.JMSSender.waitForResponseAndProcess(JMSSender.java:435)
at org.apache.axis2.transport.jms.JMSSender.sendOverJMS(JMSSender.java:369)
at org.apache.axis2.transport.jms.JMSSender.sendMessage(JMSSender.java:192)
at org.apache.axis2.transport.base.AbstractTransportSender.invoke(AbstractTransportSender.java:112)
at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:442)
at org.apache.synapse.core.axis2.DynamicAxisOperation$DynamicOperationClient.send(DynamicAxisOperation.java:185)
at org.apache.synapse.core.axis2.DynamicAxisOperation$DynamicOperationClient.executeImpl(DynamicAxisOperation.java:167)
at org.apache.axis2.client.OperationClient.execute(OperationClient.java:149)
at org.apache.synapse.core.axis2.Axis2FlexibleMEPClient.send(Axis2FlexibleMEPClient.java:603)
at org.apache.synapse.core.axis2.Axis2Sender.sendOn(Axis2Sender.java:85)
at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.send(Axis2SynapseEnvironment.java:511)
at org.apache.synapse.endpoints.AbstractEndpoint.send(AbstractEndpoint.java:384)
at org.apache.synapse.endpoints.AddressEndpoint.send(AddressEndpoint.java:65)
at org.apache.synapse.mediators.builtin.CallMediator.handleNonBlockingCall(CallMediator.java:276)
at org.apache.synapse.mediators.builtin.CallMediator.mediate(CallMediator.java:121)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:108)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:70)
at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:158)
at org.apache.synapse.mediators.MediatorWorker.run(MediatorWorker.java:80)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

I'm not sure this is related. But I think you need <property action="remove" name="OUT_ONLY" value="true"/> in the out sequence too.

Related

Sending to dynamic address endpoint

How can one send an email to a dynamic address?
Address endpoint's URI seem to be static.
Is there a way to inject a property in a address endpoint ?
Here is what I have so far :
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="sendMail" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<property expression="//email" name="email" scope="default" type="STRING"/>
<log level="custom">
<property expression="fn:concat('Sending mail to - ',get-property('mail'))" name="mail"/>
</log>
<property name="messageType" value="text/html" scope="axis2"/>
<property name="ContentType" value="text/html" scope="axis2"/>
<property name="Subject" value="File Received" scope="transport"/>
<property name="OUT_ONLY" value="true"/>
<send>
<endpoint name="mail2user">
<address uri="mailto:username#gmail.com"/>
</endpoint>
</send>
</sequence>
Thanks.
Define header "To" and use send without endpoint :
<header name="To"expression="fn:concat('mailto:', get-property('senderAddress'))"/>
<property name="OUT_ONLY" value="true"/>
<send/>
Don't forget to define transportSender "mailto" with class "org.apache.axis2.transport.mail.MailTransportSender" in axis2.xml
Here is the final code after jean-michel suggestion :
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="sendMail" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<property expression="//email" name="mailto" scope="default" type="STRING"/>
<log level="custom">
<property expression="fn:concat('Sending mail to - ',get-property('mailto'))" name="mail"/>
</log>
<property name="messageType" scope="axis2" type="STRING" value="text/html"/>
<property name="ContentType" scope="axis2" type="STRING" value="text/html"/>
<property name="Subject" scope="transport" type="STRING" value="File Received"/>
<property name="OUT_ONLY" scope="default" type="STRING" value="true"/>
<header expression="fn:concat('mailto:', get-property('mailto'))" name="To" scope="default"/>
<property name="OUT_ONLY" scope="default" type="STRING" value="true"/>
<send/>
</sequence>

WSO2 API Manager, where can I find the log of gateway?

such as the title, where can i find the log of gateway which is only about the api`s request and response?
in the file of wso2-apigw-trace.log,I can find nothing.
You can write synapse wire logs to a separate file with an appender like this.
# WIRE_LOGFILE is set to be a DailyRollingFileAppender using a PatternLayout.
log4j.appender.WIRE_LOGFILE=org.wso2.carbon.utils.logging.appenders.CarbonDailyRollingFileAppender
log4j.appender.WIRE_LOGFILE.File=${carbon.home}/repository/logs/${instance.log}/wso2wire${instance.log}.log
log4j.appender.WIRE_LOGFILE.Append=true
log4j.appender.WIRE_LOGFILE.layout=org.wso2.carbon.utils.logging.TenantAwarePatternLayout
log4j.appender.WIRE_LOGFILE.layout.ConversionPattern=TID: [%T] [%S] [%d] %P%5p {%c} - %x %m {%c}%n
log4j.appender.WIRE_LOGFILE.layout.TenantPattern=%U%#%D [%T] [%S]
log4j.appender.WIRE_LOGFILE.threshold=DEBUG
log4j.logger.org.apache.synapse.transport.http.wire=DEBUG, WIRE_LOGFILE
log4j.additivity.org.apache.synapse.transport.http.wire=false
If you want to log request and response with a correlation id, you can write a custom sequence. Correlation id can be taken from message_id like this.
You can also get access to the log via Log Analyzer UI in Admin Portal.
Here are the instructions on how to do this in WSO2 API Cloud (hosted version of API Manager).
If you want to have details of the calls to the backend and responses in the logs, you need to also add mediation policies that would output the data. This can be done on the second step of API editing ("Implement"), as shown in the picture below:
API Cloud has these sequences pre-installed. For your own API Manager deployment, you would have to upload them manually. Here are the XML files:
In Flow:
<sequence name="debug_in_flow" xmlns="http://ws.apache.org/ns/synapse">
<log level="full" />
<log level="custom">
<property name="Host" expression="get-property('transport', 'Host')"/>
<property name="Context" expression="get-property('To')"/>
<property name="HTTP_METHOD" expression="get-property('axis2', 'HTTP_METHOD')"/>
<property name="Resource" expression="$axis2:REST_URL_POSTFIX"/>
<property name="Origin" expression="get-property('transport', 'Origin')"/>
<property name="Content-Type" expression="get-property('transport', 'Content-Type')"/>
</log>
</sequence>
Out Flow:
<sequence name="debug_out_flow" xmlns="http://ws.apache.org/ns/synapse">
<log level="full" />
<log level="custom">
<property name="EndPoint" expression="get-property('ENDPOINT_PREFIX')"/>
<property name="Content-Type" expression="get-property('transport', 'Content-Type')"/>
</log>
</sequence>
Fault Flow:
<sequence xmlns="http://ws.apache.org/ns/synapse" name="debug_json_fault">
<log level="custom">
<property xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"
xmlns:ns3="http://org.apache.synapse/xsd"
name="ERROR_CODE"
expression="get-property('ERROR_CODE')"/>
<property xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"
xmlns:ns3="http://org.apache.synapse/xsd"
name="ERROR_MESSAGE"
expression="get-property('ERROR_MESSAGE')"/>
<property xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"
xmlns:ns3="http://org.apache.synapse/xsd"
name="ERROR_DETAIL"
expression="get-property('ERROR_DETAIL')"/>
<property xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"
xmlns:ns3="http://org.apache.synapse/xsd"
name="ERROR_EXCEPTION"
expression="get-property('ERROR_EXCEPTION')"/>
<property name="EndPoint" expression="get-property('ENDPOINT_PREFIX')"/>
<property name="Content-Type" expression="get-property('transport', 'Content-Type')"/>
</log>
<payloadFactory>
<format>
<am:fault xmlns:am="http://wso2.org/apimanager">
<am:code>$1</am:code>
<am:type>Status report</am:type>
<am:message>Runtime Error</am:message>
<am:description>$2</am:description>
</am:fault>
</format>
<args>
<arg expression="$ctx:ERROR_CODE"/>
<arg expression="$ctx:ERROR_MESSAGE"/>
</args>
</payloadFactory>
<filter xpath="$ctx:CUSTOM_HTTP_SC">
<then>
<property name="HTTP_SC" expression="$ctx:CUSTOM_HTTP_SC" scope="axis2"/>
</then>
<else>
<property name="HTTP_SC" value="500" scope="axis2"/>
</else>
</filter>
<class name="org.wso2.carbon.apimgt.usage.publisher.APIMgtFaultHandler"/>
<property name="RESPONSE" value="true"/>
<header name="To" action="remove"/>
<property name="NO_ENTITY_BODY" scope="axis2" action="remove"/>
<property name="ContentType" scope="axis2" action="remove"/>
<property name="Authorization" scope="transport" action="remove"/>
<property name="Host" scope="transport" action="remove"/>
<property name="Accept" scope="transport" action="remove"/>
<property name="X-JWT-Assertion" scope="transport" action="remove"/>
<property name="messageType" value="application/json" scope="axis2"/>
<send/>
<drop/>
I think you can find those log records from http_access_<Date>.log
File path: <APIM Home>/repositary/logs/http_access_<Date>.log

Unable to use call mediator in APIM 2.0.0

I've tried this on 1.10.0 and 2.0.0
On 1.10.0, you can disable the JMS sender in repository/conf/axis2/axis2_blocking_client.xml and use the call mediator in blocking mode. This is described in this blog post: http://shenavid.blogspot.nl/2016/08/invoking-external-endpoints-using-call.html and works ok. However this method does not work in 2.0.0 even though the related issue is marked as resolved.
Has anyone else tested this on 2.0.0 already? Or found an other workaround?
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="opal_auth_and_send"
onError="gov:apimgt/customsequences/fault/json_fault.xml"
trace="enable" xmlns="http://ws.apache.org/ns/synapse">
<property description="ORG_PAYLOAD" expression="$body/child::node()"
name="ORG_PAYLOAD" scope="default" type="STRING"/>
<property description="URL_POSTFIX"
expression="get-property('axis2', 'REST_URL_POSTFIX')"
name="URL_POSTFIX" scope="default" type="STRING"/>
<property action="remove" description="Remove REST_URL_POSTFIX"
name="REST_URL_POSTFIX" scope="axis2"/>
<property action="remove" description="Remove transport headers"
name="TRANSPORT_HEADERS" scope="axis2"/>
<header name="Authorization" scope="transport" value="Basic xxxxxxxx"/>
<property description="set messageType" name="messageType"
scope="transport" type="STRING" value="application/json"/>
<call blocking="true" description="Get Auth token (blocking)">
<endpoint>
<http method="get" trace="enable" uri-template="https://opal-demo34.ortec-finance.com/auth/api/token"/>
</endpoint>
</call>
<property description="Get Token from Response"
expression="json-eval($.token)" name="TOKEN" scope="default" type="STRING"/>
<property action="remove" description="Remove transport headers"
name="TRANSPORT_HEADERS" scope="axis2"/>
<log description="Log auth result" level="full"/>
<property description="Restore REST_URL_POSTFIX"
expression="get-property('URL_POSTFIX')" name="REST_URL_POSTFIX"
scope="axis2" type="STRING"/>
<payloadFactory description="Restore Payload" media-type="json">
<format>$1</format>
<args>
<arg evaluator="xml" expression="get-property('ORG_PAYLOAD')"/>
</args>
</payloadFactory>
<header expression="get-property('TOKEN')" name="Authorization" scope="transport"/>
</sequence>
Thanks,
Danny

WSO2 ESB overwrites a ContentType property

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

How can I retrieve HTTP status returned by REST service in WSO2 ESB?

My Proxy Service deployed on ESB is calling another standalone REST service. This service returns HTTP status 200 along with some data in the response body. My question is how I can retrieve HTTP status from response. Here is my configuration:
<proxy name="CQProxy"
transports="https http"
startOnLoad="true"
trace="disable">
<description/>
<target>
<inSequence>
<switch source="get-property('Action')">
<case regex="getTaskTicket">
<sequence key="GetTaskTicket"/>
</case>
<default/>
</switch>
</inSequence>
<outSequence>
<log>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="Status"
expression="get-property('HTTP_SC')"/>
</log>
<send/>
</outSequence>
<faultSequence/>
</target>
<publishWSDL key="gov:/services/cqproxy/CQProxy.wsdl">
<resource location="CQProxy.xsd" key="gov:/services/cqproxy/CQProxy.xsd"/>
</publishWSDL>
</proxy>
<sequence name="GetTaskTicket">
...
<property name="REST_URL_POSTFIX"
value="/16783484?oslc.select=dcterms:title,oslc_cm:status"
scope="axis2"
type="STRING"/>
<property name="HTTP_METHOD" value="GET" scope="axis2" type="STRING"/>
<send>
<endpoint>
<address uri="http://.../simpleQuery"
format="rest"/>
<property name="OSLC-Core-Version" value="2.0" scope="transport"/>
<property name="Accept" value="application/rdf+xml" scope="transport"/>
</endpoint>
</send>
</sequence>
...
I tried the following code:
<log>
<property xmlns:ns="http://org.apache.synapse/xsd" name="Status" expression="get-property('HTTP_SC')"/>
</log>
And this one too:
<log>
<property xmlns:ns="http://org.apache.synapse/xsd" name="Status" expression="get-property('axis2', 'HTTP_SC')"/>
</log>
But all of them returned null.
After reading WSO2 documentation in more details, I found the right answer:
<property xmlns:ns="http://org.apache.synapse/xsd" name="Status" expression="$axis2:HTTP_SC"/>
It is weird that the documented get-property('axis2', 'HTTP_SC') does not work.
Posting the solution that worked for me:
<property scope="default" type="STRING" name="HTTP_STATUS_CODE" expression="get-property('axis2', 'HTTP_SC')"/>
<log level="custom">
<property expression="get-property('HTTP_STATUS_CODE')" name="HTTP status code received: "/>
</log>