I'm having troubles with my proxy response after sending an email.
The proxy responds with a blank payload.
I'm using WSO2 Enterprise Service Bus 4.9.0.
This is the part of my proxy that sends email and respond the proxy with an error message:
<payloadFactory media-type="xml">
<format key="ErrorEmailTemplate"/>
</payloadFactory>
<property name="messageType" scope="axis2" type="STRING" value="text/html"/>
<property name="ContentType" scope="axis2" type="STRING" value="text/html"/>
<property name="OUT_ONLY" scope="default" type="STRING" value="true"/>
<property name="FORCE_SC_ACCEPTED" scope="axis2" type="STRING" value="true"/>
<header expression="fn:concat('mailto:', get-property('ErrorEmailAddress'))" name="To" scope="default"/>
<call/>
<payloadFactory media-type="xml">
<format>
<updateEmployeesResponse>
<status>ERROR</status>
</updateEmployeesResponse>
</format>
<args/>
</payloadFactory>
<respond description="Respond to Client"/>
I don't know what's the problem, maybe with Header change while sending email.
FORCE_SC_ACCEPTED is used to send back a blank response at the end of the mediation with http status code 202.
If you want to send back your own response, remove this property
Related
I need to get a token from Cognito but I don't know how to get it through enterprise integrator. I have client_id and client_secet and endpoint also. But I 'm not able to get the token seems I'm not calling the endpoint properly with proper parameter.
After getting the token I need to cache it till the token expires so I don't have to call again and again
here is the code I'm trying
<cache id="cache-sample" scope="per-host" collector="false" hashGenerator="org.wso2.carbon.mediator.cache.digest.DOMHASHGenerator" timeout="5000">
<implementation type="memory" maxSize="1000"/>
</cache>
<header name="client_id" scope="transport" value="XXXXXXXXXXXXXXXXX"/>
<header name="client_secret" scope="transport" value="XXXXXXXXXXXXXXXXXXX"/>
<header name="Content-Type" scope="transport" value="application/json"/>
<property name="DISABLE_CHUNKING" scope="axis2" type="STRING" value="true"/>
<call>
<endpoint>
<address uri="https://xcxxxxxxxxxx.auth.us-east-1.amazoncognito.com/oauth2/token"/>
</endpoint>
</call>
<property name="RESPONSE" value="true" scope="default" type="STRING"/>
<cache scope="per-host" collector="true"/>
<respond/>
<?xml version="1.0" encoding="UTF-8"?>
<api context="/api/myService" name="myService-api" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST" uri-template="/getToken">
<inSequence>
<script language="js"><![CDATA[var payload = mc.getPayloadXML();
var log = mc.getServiceLog();
var client_id = payload..*::client_id.toString();
var client_secret = payload..*::client_secret.toString();
mc.setProperty("client_id", client_id);
mc.setProperty("client_secret", client_secret);]]>
</script>
<payloadFactory media-type="json">
<format/>
<args/>
</payloadFactory>
<property name="ContentType" scope="axis2" type="STRING" value="application/x-www-form-urlencoded"/>
<property expression="fn:concat($ctx:client_id,':',$ctx:client_secret)" name="credentials" scope="default" type="STRING"/>
<property expression="fn:concat('Basic ', base64Encode($ctx:credentials))" name="Authorization" scope="transport" type="STRING" xmlns:ns="http://org.apache.synapse/xsd"/>
<property name="FORCE_POST_PUT_NOBODY" scope="axis2" type="BOOLEAN" value="true"/>
<property name="DISABLE_CHUNKING" scope="axis2" type="STRING" value="true"/>
<cache
collector="false"
hashGenerator="org.wso2.carbon.mediator.cache.digest.DOMHASHGenerator"
id="cognito-token"
scope="per-host"
timeout="3600">
<onCacheHit>
<log level="custom">
<property expression="/" name="[usage-service-api]:: CHACHE HIT"/>
</log>
<respond/>
</onCacheHit>
<implementation maxSize="50" type="memory"/>
</cache>
<call>
<endpoint>
<http method="post" uri-template="https://xxxxxxxxxxx.amazoncognito.com/oauth2/token?grant_type=client_credentials"/>
</endpoint>
</call>
<property name="RESPONSE" scope="default" type="STRING" value="true"/>
<cache collector="true" id="cognito-token" scope="per-host"/>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
For first Call cache miss will happen in that case it will call the endpoint and store it in the cache
for the second call and onwards till the time expires for the same call it will hit the cache i.e. Cache hit then It will respond from onCacheHit mediator
<onCacheHit>
<respond/>
</onCacheHit>
and
But after cache hit it will skip any execution of any statement written after cache Mediator. So So keep it in some other sequence if you are writing in some sequence
You can have more than one resources in API.
If you want to know how to call this API then see this getting cognito acces_token with wso2 esb
<log level="custom">
<property expression="/" name="[usage-service-api]:: CHACHE HIT"/>
</log>
The above block of code logs the content of the cache on CACHE HIT
I am trying to send a message to JMS queue, the queue name is dynamic and it will be fetched from DB.
Along with the queue name, connection factory details, initial context factory, provider url are concatenated and saved in a property (endpt) in wso2 esb.
I want to use the final concatenated string (endpt) in send mediator as endpoint, i have given endpoint type as XPATH and called the variable using $ctx:endpt (endpt is the property where i have final formed URL), and it is not working.
<?xml version="1.0" encoding="UTF-8"?>
<property
expression="fn:concat('jms://', $ctx:queueName, '?
transport.jms.ConnectionFactoryJNDIName=', $ctx:connectionFactory,'&java.naming.factory.initial=weblogic.jndi.WLInitialContextFactory&java.naming.provider.url=', 't3://localhost:7003,localhost:7004', '&transport.jms.DestinationType=queue')"
name="endpt" scope="default" type="STRING"
xmlns="http://ws.apache.org/ns/synapse"
xmlns:ns="http://org.apache.synapse/xsd"/>
EDIT 1: Code below is the complete sequence being called from a proxy service,
I need to send $body to the endpoint defined in To header. The same worked when i define a endpt in send mediator in the insequence of proxy service, but when i call the above sequence (using sequence mediator) from the proxy service, null message is sent to JMS queue.
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="sendtoconsumer" xmlns="http://ws.apache.org/ns/synapse">
<property name="OUT_ONLY" scope="default" type="STRING" value="true"/>
<property expression="//*[name() = 'CONSUMER_REFERENCE']/text()"
name="topic" scope="default" type="STRING"
xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:ns="http://org.apache.synapse/xsd"/>
<property expression="fn:substring-before($ctx:topic,'//')"
name="topicval" scope="default" type="STRING"
xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:ns="http://org.apache.synapse/xsd"/>
<property
expression="fn:substring-before(fn:substring-after($ctx:topic,'//'),'#')"
name="queueName" scope="default" type="STRING"
xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:ns="http://org.apache.synapse/xsd"/>
<property expression="fn:substring-after($ctx:topic,'#')"
name="connectionFactory" scope="default" type="STRING"
xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:ns="http://org.apache.synapse/xsd"/>
<log level="custom">
<property expression="$ctx:pubRequest" name="body" xmlns:ns="http://org.apache.synapse/xsd"/>
<property expression="$ctx:topic" name="topic" xmlns:ns="http://org.apache.synapse/xsd"/>
<property expression="$ctx:topicval" name="topicval" xmlns:ns="http://org.apache.synapse/xsd"/>
</log>
<switch source="get-property('topicval')" xmlns:ns="http://org.apache.synapse/xsd">
<case regex="mq:"/>
<case regex="java:">
<property
expression="fn:concat('jms://', $ctx:queueName, '?transport.jms.ConnectionFactoryJNDIName=', $ctx:connectionFactory,'&java.naming.factory.initial=weblogic.jndi.WLInitialContextFactory&java.naming.provider.url=', 't3://localhost:7003,localhost:7004', '&transport.jms.DestinationType=queue')"
name="endpt" scope="default" type="STRING"/>
<log level="custom">
<property expression="$ctx:endpt" name="sendvalue"/>
</log>
<header expression="get-property('endpt')" name="To"/>
<send>
<endpoint>
<default/>
</endpoint>
</send>
</case>
<case regex="http:"/>
<default>
<log level="custom">
<property expression="$ctx:topic" name="poda"/>
</log>
</default>
</switch>
</sequence>
The Xpath Endpoint is a key-expression - i.e., points to a resource - either in the registry, or in the local Endpoints.
What you actually need is a default endpoint and a header "To" with the endpoint value:
<header name="To" expression="get-property('endpt')"/>
<send>
<endpoint>
<default/>
</endpoint>
</send>
i am trying to implement logic that if during execution of sequence any error occurs, like e.g JMS endpoint is invalid, So sequence should drop here and log the message.
The actual mediation is like below:
Validate-->Clone-->Log Clone mediation snapshot attached.
My Service Code is:
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="AdapterService"
transports="jms"
statistics="disable"
trace="disable"
startOnLoad="true">
<target>
<inSequence>
<log level="full" separator="..... XML Received..."/>
<validate source="//DOCUMENT03">
<schema key="conf:/DOCUMENT03_CUSTOM.xsd"/>
<on-fail>
<makefault version="pox">
<reason value="Invalid XML"/>
<detail>Error while validating XML at Adapter Service.</detail>
</makefault>
<log level="full" category="ERROR" separator="... XML Error..."/>
<drop/>
</on-fail>
</validate>
<clone>
<target>
<sequence>
<script language="js">mc.getEnvelope().getBody().getFirstElement().getFirstElement().getFirstElement().detach();</script>
<log level="full"/>
<property name="OUT_ONLY" value="true" scope="default" type="STRING"/>
<send>
<endpoint>
<address uri=**"jms:/BookingMessage?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&java.naming.provider.url=tcp://1929.168.1.113:61616&transport.jms.DestinationType=queue"**
format="pox">
<timeout>
<duration>10</duration>
<responseAction>fault</responseAction>
</timeout>
<suspendOnFailure>
<errorCodes>101507,101505,101503</errorCodes>
<progressionFactor>1.0</progressionFactor>
<maximumDuration>10</maximumDuration>
</suspendOnFailure>
<markForSuspension>
<errorCodes>101508,101504</errorCodes>
<retriesBeforeSuspension>5</retriesBeforeSuspension>
<retryDelay>10</retryDelay>
</markForSuspension>
</address>
</endpoint>
</send>
<payloadFactory media-type="xml">
<format>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>$1</soapenv:Body>
</soapenv:Envelope>
</format>
<args>
<arg xmlns:tns="http://com.sanomalearning/cdm/finance/generalledger/v1"
evaluator="xml"
expression="//DOCUMENT03/CMMHeader"/>
</args>
</payloadFactory>
<log level="full"/>
<property name="OUT_ONLY" value="true" scope="default" type="STRING"/>
<send>
<endpoint key="conf:/CMMHeaderQueueUrl"/>
</send>
<log level="full" separator="Message Sent to Queue"/>
</sequence>
</target>
</clone>
</inSequence>
<outSequence>
<send/>
</outSequence>
<faultSequence>
<log level="custom" separator=",">
<property name="text" value="***FAult Handler***"/>
</log>
<property name="SET_ROLLBACK_ONLY" value="true" scope="axis2"/>
<drop/>
<log level="custom">
<property name="text" value="An unexpected error occured"/>
<property name="message" expression="get-property('ERROR_MESSAGE')"/>
<property name="code" expression="get-property('ERROR_CODE')"/>
<property name="detail" expression="get-property('ERROR_DETAIL')"/>
<property name="exception" expression="get-property('ERROR_EXCEPTION')"/>
</log>
<drop/>
</faultSequence>
</target>
<parameter name="transport.jms.ContentType">
<rules>
<jmsProperty>contentType</jmsProperty>
<default>application/xml</default>
</rules>
</parameter>
<parameter name="transport.jms.ConnectionFactory">myQueueConnectionFactory</parameter>
<parameter name="transport.jms.DestinationType">queue</parameter>
<parameter name="transport.jms.Destination">AdapterService.01.Request.Queue</parameter>
<description/>
</proxy>
Now when i execute this service after receiving request from queue, it is not sending message to invalid queue but sending message to second Url. Now i want if message is not sent to invalid endpoint then sequence should dropped. The invalid url is Bold.
AFAIK you can not define two send mediators under the same target in one clone mediator instead you have to define those inside two different targets.
Also would be helpful if you can elaborate your requirement a bit more. For a solution with regard to JMS endpoint is invalid issue what you can do is define a drop mediator inside the fault sequence.
I have configured Apache ActiveMQ with transaction and CLIENT_ACKNOWLEDGE in WSO2 ESB 4.7.0. The axis2.xml config is :
<parameter name="transport.jms.SessionTransacted">true</parameter>
<parameter name="transport.jms.SessionAcknowledgement" locked="true">CLIENT_ACKNOWLEDGE</parameter>
I have a simple passthrough proxy with jms transport which passes the messages in the JMS queue to a jax-rs service. The proxy code is :
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="MediaMoveQueue"
transports="jms"
startOnLoad="true"
trace="enable">
<description/>
<target>
<inSequence>
<property name="messageType" value="application/json" scope="axis2"/>
<property name="ContentType" value="application/json" scope="axis2"/>
<send receive="JmsRollbackSequence">
<endpoint>
<address uri="http://192.168.1.2:9766/RestMediaMove_1.0.0/services/rest_media_move_i_f/restmediamoveif/hello"/>
</endpoint>
</send>
<log level="custom">
<property name="In MediaMoveQueue JMSERROR"
expression="get-property('JMSERROR')"/>
</log>
<switch source="get-property('JMSERROR')">
<case regex="true">
<property name="SET_ROLLBACK_ONLY" value="true" scope="axis2"/>
<log level="custom">
<property name="In MediaMoveQueue Transaction Action"
value="Rollbacked"/>
</log>
</case>
<case regex="false">
<log level="custom">
<property name="In MediaMoveQueue Transaction Action"
value="Committed"/>
</log>
</case>
<default>
<property name="SET_ROLLBACK_ONLY" value="true" scope="axis2"/>
<log level="custom">
<property name="In MediaMoveQueue Transaction Action default"
value="Rollbacked"/>
</log>
</default>
</switch>
</inSequence>
<outSequence>
<log level="full">
<property name="test" value="IN outsequence"/>
</log>
<send/>
</outSequence>
</target>
<parameter name="transport.jms.ContentType">
<rules>
<jmsProperty>contentType</jmsProperty>
<default>application/json</default>
</rules>
</parameter>
</proxy>
The JmsRollbackSequence sequence receives the reply from the jax-rs service and depending on the reply success or failure returned, I would like to rollback the JMS transaction. But if I set the property in the JmsRollbackSequence it has absolutely no effect ( I tried it first before using the sequence shown below). The transaction is never rolled back. The rollback works only if the property is set in the inSequence. Here is the code for the JmsRollbackSequence :
<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="JmsRollbackSequence">
<property name="JMSERROR" value="true"/>
<log level="full">
<property name="test" value="IN JmsRollbackSequence"/>
</log>
</sequence>
So I tried to set up a property called JMSERROR in the JmsRollbackSequence and by reading it after the send mediator in the inSequence I thought I can roll back the transaction in the inSequence. But this does not work either. The switch case in inSequence is called before the property is set up in JmsRollbackSequence so when I read it it always returns null.
So my questions are :
1) Can we set
in a sequence? Why does it not work in JmsRollbackSequence?
2) As mediators are supposed to be called sequentially, why does the switch case in inSequence run before the JmsRollbackSequence has a chance to read the reply and set up the JMSERROR property?
"send" mediator is asynchronous : inSequence will continue his job and JMS transaction will be commited before the response arrive in your JmsRoolbackSequence.
use "callout" mediator for synchronous calls and create a faultSequence in your proxy to deal with errors and rollback your transaction :
<faultSequence>
<property name="SET_ROLLBACK_ONLY" value="true" scope="axis2"/>
</faultSequence>
I wish to set an array in WSO2ESB in my scenario.
I am sending two parameters to database and getting number of rows but I need only one row.
My configuration is
<target>
<sequence>
<property name="partybranchid"
expression="get-property('partybranchid')"
scope="default"
type="STRING"/>
<payloadFactory>
<format>
<p:Select_MailDetails_Op xmlns:p="http://ws.wso2.org/dataservice">
<xs:assetid xmlns:xs="http://ws.wso2.org/dataservice">$1</xs:assetid>
<xs:partybranchid xmlns:xs="http://ws.wso2.org/dataservice">$2</xs:partybranchid>
</p:Select_MailDetails_Op>
</format>
<args>
<arg expression="get-property('assetid')"/>
<arg expression="get-property('partybranchid')"/>
</args>
</payloadFactory>
<log level="full"/>
<send receive="Mail_Seq">
<endpoint>
<address uri="http://localhost:9764/services/massetparametersetdetail_DataService/"
format="soap11"/>
</endpoint>
</send>
</sequence>
</target>
and I am receiving data in this sequence:
<log><property xmlns:v="http://ws.wso2.org/dataservice" xmlns:ns="http://org.apache.synapse/xsd"
name="primarymail" action="set"
expression="//v:primarymail/text()"
scope="default"
type="STRING"/></log>
<iterate xmlns:v="http://ws.wso2.org/dataservice"
xmlns:ns="http://org.apache.synapse/xsd"
id="Mail"
expression="//v:Datalist">
<target>
<sequence>
<property xmlns:v="http://ws.wso2.org/dataservice" xmlns:ns="http://org.apache.synapse/xsd"
name="primarymail"
expression="//v:primarymail/text()"
scope="default"
type="STRING"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="assetname"
expression="//assetname/text()"
scope="default"
type="STRING"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="assetcode"
expression="//assetcode/text()"
scope="default"
type="STRING"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="activityname"
expression="//activityname/text()"
scope="default"
type="STRING"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="username"
expression="//username/text()"
scope="default"
type="STRING"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="parametername"
expression="//parametername/text()"
scope="default"
type="STRING"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="uomcode"
expression="//uomcode/text()"
scope="default"
type="STRING"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="tododetails"
expression="fn:concat('AssetName:',get-property('assetname'),',','AssetCode:',get-property('assetcode'),',','ActivityName:',get-property('activityname'),',','UserName:',get-property('username'),',','ParameterName:',get-property('parametername'),',','UomCode:',get-property('uomcode'))"
scope="default"
type="STRING"/>
<log><property xmlns:v="http://ws.wso2.org/dataservice" xmlns:ns="http://org.apache.synapse/xsd"
name="primarymail" action="set"
expression="//v:primarymail/text()"
scope="default"
type="STRING"/></log>
</sequence>
</target>
</iterate>
</sequence>
and I am getting response like below but I want to send a mail only once.
Here my mailid is repeating. How can I take out this mail id?
response, primarymail =
mail#myunisoft.commail#myunisoft.commail#myunisoft.commail#myunisoft.commail#myunisoft.commail#myunisoft.commail#myunisoft.commail#myunisoft.commail#myunisoft.commail#myunisoft.com
How can I take single mail for this?
Your webservice response is a SOAP message and What you get in to any mediator in ESB, is that particular incoming message. You cannot directly have an array of values.
- One option is to use a class mediator and extract your desired value/s and set that value to a property in message context and use it.
- if the response payload can be altered in your scenario, return the response with a known delimiter and use xpath String operations to get your value.