I tried to create a custom policy, with a purpose a mask of service:
Original Services in API:
http://API/v1/profile
http://API/v1/account
With mask:
http://API/v1/user-profile
http://API/v1/user-account
And combination the answer of User Bee this a solution for this problem:
<switch source="get-property('axis2', 'REST_URL_POSTFIX')">
<case regex="/v1/kyc-profile">
<property name="REST_URL_POSTFIX" value="/v1/profile" scope="axis2"/>
</case>
<case regex="/v1/kyc-account">
<property name="REST_URL_POSTFIX" value="/v1/account" scope="axis2"/>
</case>
</switch>
But this solution only works where the services is static, but I have others services, similar to:
http://API/v1/user-profile/{id-user}/details
http://API/v1/user-profile/{id-user}?expand=some_information
For the last service I have this:
<switch source="get-property('axis2', 'REST_URL_POSTFIX')">
<case regex="v1/user-profile/[\/\w\W]*">
<property name="REST_URL_POSTFIX" value="/v2/cliente/{id-user}?expand=some_information" scope="axis2"/>
</case>
</switch>
[/\w\W]* This part is regular expression for {id-user}?expand=some_information and similar.
The problem is: I need put dynamic value because the property value (<property name="REST_URL_POSTFIX" value="THIS" scope="axis2"/>) takes this text, example:
Service before to policie
http://API/v1/user-profile/1?expand=some_information
Service after to policie
http://API/v1/user-profile/{id-user}?expand=some_information
My questions are:
How to put a dynamic value for the services similar to: http://API/v1/user-profile/{id-user}?expand=some_information?
For the other service, http://API/v1/user-profile/{id-user}/details I have the similar situacion, How a resolve?
In your mediation sequence, try changing the backend URL as follows.
http://API/v1/user-profile/{uri.var.id-user}?expand=some_information
Example:
<switch source="get-property('axis2', 'REST_URL_POSTFIX')">
<case regex="v1/user-profile/[\/\w\W]*">
<property name="REST_URL_POSTFIX" value="/v2/cliente/{uri.var.id-user}?expand=some_information" scope="axis2"/>
</case>
</switch>
Related
Is there a way to read the properties from file in wso2 using property mediator?
I'm injecting an address uri from the file.properties, and passing the file path as -Dproperties.file.path argument to the startup script, it is able to resolve the varibale only within the address endpoint's uri attribute using the syntax $FILE:variableName as below:
<call>
<endpoint>
<address uri="$FILE:uploadPath">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>1</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</address>
</endpoint>
</call>
But I also have the need to use the same property, do a minor transformation and pass it to a class mediator,
I've tried the below approaches and none of them are working.
<log level="custom">
<property expression="$FILE:uploadPath" name="file-path-1"/>
<property expression="$ctx:uploadPath" name="file-path-2"/>
<property expression="$axis2:uploadPath" name="file-path-3"/>
<property expression="$trp:uploadPath" name="file-path-4"/>
<property expression="$axis2:POST_TO_URI" name="POST_TO_URI"/>
</log>
Below are the versions of OS and tools that I'm using.
OS: Mac os catalina,
WSO2: micro-integrator 1.2.0, Integration sutdio - 7.1.0
Some time ago, i was struggling with similar issue, to try using $FILE: in dockered microintegrator . After checking sourcecode i realized that there is no implemented reading in property mediator, and that works only in endpoints... I belive that is because of security reason?
But, there is some workaround, which I'm not a big fan. You could use Property and ScriptMediator:
<property xmlns:ns="http://org.apache.synapse/xsd" name="propPath" expression="get-property('system','properties.file.path')" scope="default" type="STRING"/>
<script language="js"><![CDATA[
var path = java.nio.file.Paths.get(mc.getProperty('propPath'));
var fromFile = java.nio.file.Files.readAllLines(path, java.nio.charset.StandardCharsets.UTF_8);
mc.setProperty('line1',fromFile.get(0).toString());
mc.setProperty('line2',fromFile.get(1).toString());
]]></script>
Of course you got full line, but if you tweak this ScriptMediator, you can have what you want in separate properties.
I am working with the WSO2 ESB 6.5.0 and am using the fileconnector-2.0.21 version for file operations. The proxy service that I'm building is intended to read the files from a certain source path and merge the contents into a file at the destination path.
The content of the proxy service artifact is below
<?xml version="1.0" encoding="UTF-8"?>
<proxy name="FileMergeProxy" startOnLoad="true" transports="http https" xmlns="http://ws.apache.org/ns/synapse">
<target>
<inSequence>
<log description="Combine files" level="custom" separator="| ">
<property name="statusMessage" value="Processing complete"/>
<property name="fileCreation" value="Initiating file merge"/>
<property expression="$ctx:mergeDirPath" name="sourceDir"/>
<property expression="$ctx:finalDirPath" name="destDir"/>
<property expression="$ctx:outputFilePattern" name="pattern"/>
<property expression="fn:concat('file:///', $ctx:mergeDirPath)" name="sourceDir1" scope="default" type="STRING"/>
property expression="fn:concat('file:///', $ctx:finalDirPath)" name="destDir1" scope="default" type="STRING"/>
</log>
<fileconnector.mergeFiles>
<source>{$ctx:mergeDirPath}</source>
<destination>{$ctx:finalDirPath}</destination>
<filePattern>{$ctx:outputFilePattern}</filePattern>
</fileconnector.mergeFiles>
<log description="Processing complete" level="custom" separator="| ">
<property name="doneMessage" value="File merge processing complete"/>
</log>
</inSequence>
<outSequence/>
<faultSequence>
<log level="custom">
<property name="text" value="An unexpected error occured"/>
<property expression="get-property('ERROR_MESSAGE')" name="message"/>
<property expression="get-property('ERROR_DETAIL')" name="errordetail"/>
</log>
<send description="Send Error Information"/>
</faultSequence>
</target>
</proxy>
I'm invoking the service with the following parameters as a JSON file
{
"mergeDirPath": "C://temp//merge//",
"finalDirPath": "C://temp//final//finalcontent.txt",
"outputFilePattern": "\\*txt"
}
When I call the service after deploying the artifacts to the ESB engine, it creates an empty file in the destination path without merging the contents of the files in the source directory. This is the extract from the WSO2 logs.
[2020-03-23 12:48:36,683] [] INFO - LogMediator To: /services/FileMergeProxy,MessageID: urn:uuid:b569ec6a-d4fe-4763-a0ca-fb2eb868a31e correlation_id : a1c542bb-7fac-4e0b-9582-8cb1a605f618,Direction: request,Payload: { "mergeDirPath": "C://temp//merge//", "finalDirPath": "C://temp//final//finalcontent.txt", "outputFilePattern": "\\*txt" }
[2020-03-23 12:49:00,422] [] INFO - LogMediator statusMessage = Combine files| fileCreation = Initiating file merge| sourceDir = C://temp//merge//| destDir = C://temp//final//finalcontent.txt| pattern = \*txt| sourceDir1 = file:///C://temp//merge//| destDir1 = file:///C://temp//final//finalcontent.txt
[2020-03-23 12:49:02,943] [] INFO - LogMediator doneMessage = File merge processing complete
Unless I'm missing something here, shouldn't the mergeFiles be doing exactly that - merge the contents of files in a specified directory ? Any helpful suggestions or pointers are welcome. Thanks in advance.
According to the proxy you have shared, you have defined properties inside the log mediator. Define the properties outside the log mediator.
I'm developing a healthcheck API that needs to call several endpoints. The idea is that, if any of those EPs fail, I have to capture the fault and incorporate that into the response. I thought about creating a main sequence that calls other leaf sequences, and each leaf sequence has it own fault sequence.
This diagram should make things clearer:
seqA (faultSsqA)
/
mainSeq - seqB (faultSeqB)
\ seqC (faultSeqC)
If all the sequences process successfully, everything goes well and I'm able to process the response, however, if there's a fault within one of the leaf sequences, the corresponding faultsequence is executed, but I don't know how to return the flow of execution back to the main sequence. What I want is that, if a exception occurs in sequence B, fault sequence B is executed and then the execution flow goes back to the main sequence and then to sequence C.
Even better it would be if I could execute all the leaf sequences in pararel, and just gather all the results in the end. I know that iterate mediator sort of do that, but from what I understand the semantics are not the same of what I want.
Anyone has thoughts on this?
EDIT: so it seems the clone mediator is what I'm looking for, however I'm still not able to get it working the way I need to. Since I'll be connecting to different platforms, the response formats are distinct. Also, I need to treat situations such as timeouts, 500 response codes, etc. Therefore, I can't simply call an endpoint from each target - for each backend platform I've created a sequence that does all this logic, and populate some properties so that I can populate the final response ("platform A = up", etc).
My expectation would be that all the target sequences would be processed in paralel
This is my main sequence. I use a clone mediator and target it to 2 different sequences, which do the actual invocation of the EP and treat the response (I'm using only 2 for now, but in the future will be many more). The sequences also update some variables to reflect the status of the backend platforms ("platform A = up", etc).
<sequence name="inSequence_healthCheck" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<clone id="healthCHeck">
<target>
<sequence>
<sequence key="healthCheck_wacs"/>
</sequence>
</target>
<target>
<sequence>
<sequence key="healthCheck_thesys"/>
</sequence>
</target>
</clone>
<loopback/>
</sequence>
This is one of the target sequences (it' very simple for now, but there should be more logic in it). Notice that I populate the property wacsStatus depending on the response.
<sequence name="healthCheck_wacs" onError="faultSequence_healthCheck_wacs" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<call>
<endpoint key="gov:ClientEquipments/endpoints/WACS/wacs_healthCheck.endpoint.xml"/>
</call>
<switch source="$axis2:HTTP_SC">
<case regex="2\d\d|4\d\d">
<property name="wacsStatus" scope="default" type="BOOLEAN" value="true"/>
</case>
<default>
<property name="wacsStatus" scope="default" type="BOOLEAN" value="false"/>
</default>
</switch>
</sequence>
And this is my outSequence, that does the aggregate:
<sequence name="outSequence_healthCheck" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<log>
<property name="step" value="START outSequence_healthCheck"/>
<property expression="$ctx:wacsStatus" name="wacsStatus"/>
<property expression="$ctx:thesysStatus" name="thesysStatus"/>
<property expression="$ctx:phStatus" name="phStatus"/>
<property expression="$ctx:naStatus" name="naStatus"/>
</log>
<property name="info" scope="default">
<ns:Information xmlns:ns="http://wso2.com"/>
</property>
<aggregate id="healthCHeck">
<completeCondition>
<messageCount max="-1" min="2"/>
</completeCondition>
<onComplete enclosingElementProperty="info" expression="s11:Body/child::* | s12:Body/child::*"
xmlns:m0="http://services.samples" xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:s12="http://www.w3.org/2003/05/soap-envelope">
<log level="full"/>
</onComplete>
</aggregate>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<payloadFactory media-type="json">
<format>
{
"WACS" : "$1",
"thesys" : "$2"
}
</format>
<args>
<arg evaluator="xml" expression="$ctx:wacsStatus"/>
<arg evaluator="xml" expression="$ctx:thesysStatus"/>
</args>
</payloadFactory>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<property name="HTTP_SC" scope="axis2" type="STRING" value="200"/>
<respond/>
</sequence>
My expectation would be that the aggregate mediator would wait for all the target sequences to execute, by then all the properties would be properly populated and I could use the payloadFactory to properly format the response. However, from the logs I can see that, even though the aggregate does aggregate all the responses from the target sequences, the properties are not properly populated and therefore the response is not correct.
Thanks.
Pedro
You should try an iterate mediator/clone & aggregate mediator (scatter-gather pattern) construction. The iterate allows you to execute multiple sequences in paralel while the aggregate will collect the responses. You can have the separate sequences deal with fault handling and return either the expected response or some fault. You can then check the aggregated result for any faults.
Here are a few samples:
Yenlo Blog
WSO2 Architecture Team
I'm configuring a proxy-service and I have three sequences: s1,s2,s3
The value of 1,2,3 is stored in a local registry variable and it's get from the registry and stored in the property called 'myProp'
now, based on the value of this myProp I would like to call one of the three sequences.
I tried this:
<sequence key="s{concat(get-property('myProp'))}"/>
but doesn't works.
This is the property code:
<property name="myProp"
expression="get-property('registry','conf:repository/myVersion2.xml')"
scope="default"
type="STRING"/>
and this is what I'm trying to do:
<filter source="get-property('myProp')"
regex=".*>1<.*"
description="filter">
<then>
<log level="custom" separator=":">
<property name="TestVersion" value="LOG_S1_TRUE"/>
<property name="TestVersion" expression="get-property('myProp')"/>
</log>
<sequence key="s{concat(get-property('myProp'))}"/>
</then>
<else>
<log level="custom" separator=":">
<property name="TestVersion" value="LOG_S1_FALSE"/>
</log>
</else>
</filter>
I get this error from the log:
TID: [0] [ESB] [2015-07-03 12:47:25,340] ERROR {org.apache.synapse.mediators.base.SequenceMediator} - Sequence named Value {name ='null', keyValue ='s{concat(get-property('myProp'))}'} cannot be found {org.apache.synapse.mediators.base.SequenceMediator}
Thanks in advance to who know how to solve it.
Regards
Claudio
Assign the keyvalue to a property first to test it, you will notice that it cannot work :)
Try:
<sequence key="{concat('s', get-property('myProp'))}"/>
I have to mapping query params to send request to endpoint in API resource in WSO2 ESB.
Those query params are optional. For example, the following are examples of calls to resource:
http://server:port/service?q1={q1}
http://server:port/service?q2={q2}&q3={q3}
I need to have a single resource to do this.
How can I do this?
Basically, I have to read query params in request and put it in the call to endpoint uri.
You can have dynamic URIs using url-mapping attribute.
Here is an example:
<api xmlns="http://ws.apache.org/ns/synapse" name="test_api" context="/testService">
<resource methods="GET" url-mapping="/*">
<inSequence>
<log level="full">
<property name="paramQ1" expression="$ctx:query.param.q1"></property>
<property name="paramQ2" expression="$ctx:query.param.q2"></property>
<property name="paramQ3" expression="$ctx:query.param.q3"></property>
</log>
<send>
<endpoint>
<address uri="http://localhost:9766/services/"></address>
</endpoint>
</send>
</inSequence>
<outSequence>
<send></send>
</outSequence>
</resource>
</api>
To validate the presence of those query params its possible to use Filter Mediator. A good example of it can be found here.
Hope it helps.