I have following code:
<property name="resultOM" scope="default" type="OM">
<test><test1>testing111</test1></test>
</property>
<log level="full">
<property name="ROOT" expression="$ctx:resultOM" />
<property name="resultOM.test" expression="$ctx:resultOM//test1" />
</log>
Then I would expect to see in logs values
ROOT = testing111
resultOM.test = testing111
and although ROOT value is fine, the value of resultOM.test is empty.
What should be the correct xpath to retrieve the child value?
Version of used WSO2ESB is 4.5.1.
A default namespace (http://ws.apache.org/ns/synapse) is defined when you create an OM type property. So you need to perform xpath expressions with namespaces. Try this;
<log level="full">
<property name="ROOT" expression="$ctx:resultOM"/>
<property name="resultOM.test" xmlns:ns="http://ws.apache.org/ns/synapse" expression="$ctx:resultOM//ns:test1"/>
</log>
Read [1] for more details.
[1] http://isharapremadasa.blogspot.com/2014/08/wso2-esb-property-mediator-performing.html
Related
I am writing an iterate mediator, the code is going in the sequence written in that iterate mediator, it is completing too (read through logs) however, it is not going to next step. Please help me with what wrong am I doing.
<iterate expression="//mpesa/prov">
<target>
<sequence>
<sequence key="ProvMapperQueue"/>
</sequence>
</target>
</iterate>
<log level="custom">
<property name="After" value="Sequence"/>
</log>
It is now printing the logs neither is API getting a response, its stuck after sequence last line is logged.
For further information copying the sequence below too:
<sequence name="ProvMapperQueue" onError="ProvMapperQueue_Error" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<log level="custom">
<property expression="$ctx:uri.var.msisdn" name="Msisdn"/>
<property name="ProvMapperQueue Sequence" value="Started"/>
</log>
<property name="messageType" scope="axis2" type="STRING" value="text/xml"/>
<property name="OUT_ONLY" scope="default" type="STRING" value="true"/>
<call>
<endpoint key="OBD_EP"/>
</call>
<log level="custom">
<property expression="$ctx:uri.var.msisdn" name="Msisdn"/>
<property name="After Calling" value=" ProvMapperQueue EP"/>
<property name="ProvMapperQueue Sequence" value="Ended"/>
</log>
<respond/>
</sequence>
Logs printing are below :
[2023-01-24 00:14:07,883] INFO {LogMediator} - {api:OBD} Msisdn = 110000171, ProvMapperQueue Sequence = Started
[2023-01-24 00:14:07,893] INFO {TimeoutHandler} - This engine will expire all callbacks after GLOBAL_TIMEOUT: 120 seconds, irrespective of the timeout action, after the specified or optional timeout
[2023-01-24 00:14:08,181] INFO {LogMediator} - {api:OBD} Msisdn = 110000171, After Calling = ProvMapperQueue EP, ProvMapperQueue Sequence = Ended
[2023-01-24 00:17:06,839] INFO {SourceHandler} - Writer null when calling informWriterError
[2023-01-24 00:17:06,841] 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 = /obd/prov/msisdn/110000171, HTTP_METHOD = GET, SOCKET_TIMEOUT = 180000, CLIENT_ADDRESS = /127.0.0.1:59198, CONNECTION http-incoming-4
Any help would mean a lot.
I think the problem is with the <respond/> mediator that you have added towards the end of the ProvMapperQueue sequence. This will stop further processing of a message and send the message back to the client[1]. That means, after it, the rest of the sequence logic will not be executed including the log mediator outside the iterate mediator.
[1] - https://docs.wso2.com/display/EI611/Respond+Mediator
Few issues with your integration. You need to remove the respond mediator from the Iterate sequence, as responding per iteration doesn't make sense. So, I believe what you need is to iterate over the entries and once done, respond back to the client. In order to wait for all the Iterations to finish you need to couple the iterate mediator with an aggregate mediator. Hence update the sequences like below.
<sequence name="ProvMapperQueue" onError="ProvMapperQueue_Error" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<log level="custom">
<property expression="$ctx:uri.var.msisdn" name="Msisdn"/>
<property name="ProvMapperQueue Sequence" value="Started"/>
</log>
<property name="messageType" scope="axis2" type="STRING" value="text/xml"/>
<property name="OUT_ONLY" scope="default" type="STRING" value="true"/>
<call>
<endpoint key="OBD_EP"/>
</call>
<log level="custom">
<property expression="$ctx:uri.var.msisdn" name="Msisdn"/>
<property name="After Calling" value=" ProvMapperQueue EP"/>
<property name="ProvMapperQueue Sequence" value="Ended"/>
</log>
</sequence>
<iterate expression="//mpesa/prov" id="iterateid">
<target>
<sequence>
<sequence key="ProvMapperQueue"/>
</sequence>
</target>
</iterate>
<aggregate id="iterateid">
<completeCondition>
<messageCount max="-1" min="-1"/>
</completeCondition>
<onComplete expression="$body/*[1]">
<payloadFactory media-type="xml">
<format>
<payload xmlns="">
<response>Done</response>
</payload>
</format>
<args/>
</payloadFactory>
<respond/>
</onComplete>
</aggregate>
Update
The issue is you have set the OUT_ONLY property in your sequence hence the aggregate is never completed since callbacks are not registered. Instead of Iterate Mediator use the Foreach Mediator for your usecase. Check the example below.
<foreach expression="//mpesa/prov">
<sequence>
<sequence key="ProvMapperQueue"/>
</sequence>
</foreach>
<log level="custom">
<property name="After" value="Sequence"/>
</log>
<payloadFactory media-type="xml">
<format>
<payload xmlns="">
<response>Done</response>
</payload>
</format>
<args/>
</payloadFactory>
<respond/>
I would like to create a input sequence where I check a param with a switch mediator. If the value of the param does not correspond to a specific string, then an error should be thrown and move the flow in the Fault sequence.
For example, I created this sequence:
<sequence name="testEquivalence" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<switch source="$ctx:uri.var.myParam">
<case regex="hello">
<log description="DISPLAY" level="full">
<property name="value" value="RIGHT VALUE FOR THE PARAM myParam"/>
</case>
<default>
<log description="FAULT" level="full">
<property name="FAULT" value="WRONG VALUE FOR THE PARAM myParam"/>
</log>
<makefault version="pox">
<reason value="Wrong value"/>
<detail expression="'Wrong value. Try with hello.'"/>
</makefault>
</default>
</switch>
</sequence>
As you can see, I want to display a log saying "RIGHT VALUE FOR THE PARAM myParam" if it is OK. Or, I would like to display a log and then stop the process in the default part to pass in the Fault sequence.
However, I created a makefault mediator to "modelize" my fault but is it possible to replace it by something more... executive to stop the process and redirect the flow in the Fault sequence like if an exception was thrown?
There is no way to throw an exception in WSO2 ESB/EI. Generally after creating a SOAPFault you want to return this to the caller of the service. A Solution is to use the Response Mediator after the Fault mediator:
<sequence name="testEquivalence" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<switch source="$ctx:uri.var.myParam">
<case regex="hello">
<log description="DISPLAY" level="full">
<property name="value" value="RIGHT VALUE FOR THE PARAM myParam"/>
</case>
<default>
<log description="FAULT" level="full">
<property name="FAULT" value="WRONG VALUE FOR THE PARAM myParam"/>
</log>
<makefault version="pox">
<reason value="Wrong value"/>
<detail expression="'Wrong value. Try with hello.'"/>
</makefault>
<respond/>
</default>
</switch>
</sequence>
I am using a property "INC" to store a incoming message(which is showing properly in logs) and doing mapping properly by payload mediator.
The modified structure that I am getting by payload is as below.(which is getting properly mapped)
Later, I am using callout mediator as below to get response from this endpoint.
using LogText to see the response.
Then adding filter as below:
<property name="INC" expression="get-property('IntRequest')" scope="default" type="STRING"/>
<property name="LogText" value="call response" scope="default" type="STRING"/>
<filter xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:platformFaults="urn:faults_2015_1.platform.webservices.com" source="//platformFaults:code/text()" regex="WS_CONCUR_SESSION_DISALLWD">
<then>
<log level="full" separator=",*Fault in Call***">
<property name="REQUEST" expression="get-property('INC')" scope="default" type="STRING" />
</log>
</then>
<else/>
</filter>
But, here I am not getting value of REQUEST.. it is showing the value of "call response"..
How will I get the value of REQUEST properly??
Try to use the enrich mediator to store the request message body
<enrich>
<source clone="true" type="body"/>
<target property="Request_Message" type="property"/>
</enrich>
then call the property
<log>
<property expression="get-property('Request_Message')" name="REQUEST"/>
</log>
where did you define "IntRequest" property in your sequence? I couldn't find it in your configuration. If you change the log level to custom it would be more clear to see the value of request in the system log
I'm looking to get a history of test runs from teamcity by calling the rest apis.
So far I found:
http://teamcity.xyz.com/app/rest/builds/65602/statistics
But this will give only stats for one run.
I found below from Teamcity api documentation, but it is not clear where I should enter the multiple build numbers
http://teamcity:8111/httpAuth/app/rest/builds?locator=BUILDS_LOCATOR&fields=build(id,number,status,buildType(id,name,projectName),statistics(property(name,value)))
has anyone tried this before??
You can achieve this through a different avenue by using the buildTypes endpoint because the locator only supports a single id dimension.
e.g.
/httpAuth/app/rest/buildTypes/id:##BUILD_TYPE##/builds?fields=build(id,number,status,buildType(id,name,projectName),statistics(property(name,value)))
This will return data similar to the following
<builds>
<build id="185" number="1.0.0.2" status="SUCCESS">
<buildType id="Website_1BuildApplication" name="1 - Build Application" projectName="Website"/>
<statistics>
<property name="ArtifactsSize" value="4201093"/>
<property name="BuildArtifactsPublishingTime" value="921"/>
<property name="BuildCheckoutTime" value="377"/>
<property name="BuildDuration" value="21791"/>
<property name="BuildDurationNetTime" value="20493"/>
<property name="buildStageDuration:artifactsPublishing" value="952"/>
<property name="buildStageDuration:buildFinishing" value="15"/>
<property name="buildStageDuration:buildStepRUNNER_6" value="19313"/>
<property name="buildStageDuration:firstStepPreparation" value="219"/>
<property name="buildStageDuration:sourcesUpdate" value="496"/>
<property name="BuildTestStatus" value="1"/>
<property name="SuccessRate" value="1"/>
<property name="TimeSpentInQueue" value="6272"/>
</statistics>
</build>
<build id="183" number="1.0.0.1" status="SUCCESS">
<buildType id="Website_1BuildApplication" name="1 - Build Application" projectName="Website"/>
<statistics>
<property name="ArtifactsSize" value="4200811"/>
<property name="BuildArtifactsPublishingTime" value="297"/>
<property name="BuildCheckoutTime" value="19500"/>
<property name="BuildDuration" value="45123"/>
<property name="BuildDurationNetTime" value="25326"/>
<property name="buildStageDuration:artifactsPublishing" value="328"/>
<property name="buildStageDuration:buildFinishing" value="140"/>
<property name="buildStageDuration:buildStepRUNNER_6" value="23603"/>
<property name="buildStageDuration:firstStepPreparation" value="265"/>
<property name="buildStageDuration:sourcesUpdate" value="19516"/>
<property name="BuildTestStatus" value="1"/>
<property name="SuccessRate" value="1"/>
<property name="TimeSpentInQueue" value="234"/>
</statistics>
</build>
</builds>
Hope this helps
I have next sequence:
<payloadFactory>
<format>
<cb:accounts/>
</format>
<args/>
</payloadFactory>
<property name="accounts" type="OM" expression="//cb:accounts" />
...
<iterate id="accountIterator" continueParent="true" sequential="true" expression="//cb:accounts/cb:accountId">
<target>
<sequence>
...
<property name="accounts" type="OM" expression="//*" />
</sequence>
</target>
</iterate>
<aggregate id="accountIterator">
<onComplete expression="$body/child::*[fn:position()=1]">
<log level="custom" />
</onComplete>
</aggregate>
<enrich>
<source type="custom" xpath="get-property('accounts')"/>
<target type="body" />
</enrich>
Why property named "accounts" which was set inside "iterate" mediator has null value outside "iterate" mediator ?
Thanks
The flow inside the iterator runs on a separate thread and it is not visible out side. Therefore you can't access a property which is set inside the iterator mediator, outside but vice versa is possible.
Before calling each iteration cycle message context will be cloned and it will only be available in the context inside iterator target. Hence, by default can not get the things doing in synapse/default scope outside the iterator. If you want to store something global, use property with operation scope.
Before iterator assign your property to operation scope
Inside iterator - do modifications
Outside the iterator - assign your property to default scope (if you want to take it back to default scope)
use below structure for example:
<!--assign your property to operation scope-->
<property name="ITERATOR_DATA_PAYLOAD"
expression="get-property('DATA_PAYLOAD')"
scope="operation"
type="OM"/>
<iterate xmlns:ns="http://org.apache.synapse/xsd"
continueParent="true"
expression="//bookstore/book"
sequential="true">
<target>
<sequence>
<!--if you want to assign the property-->
<property name="DATA_PAYLOAD"
expression="get-property('operation','ITERATOR_DATA_PAYLOAD')"
type="OM"/>
</sequence>
</target>
</iterate>
<!--Outside the iterator-->
<property xmlns:ns="http://org.apache.synapse/xsd"
name="NEW_DATA_PAYLOAD"
expression="get-property('operation','ITERATOR_DATA_PAYLOAD')"
type="OM"/>