WSO2 4.8.0 ESB conditional router - filter

i read at this url
https://docs.wso2.org/display/ESB480/Sample+157:+Conditional+Router+for+Routing+Messages+based+on+HTTP+URL,+HTTP+Headers+and+Query+Parameters
that conditional router matching a regex can be written like this:
<match type="header" source="my_custom_header2" regex="bar.*"/>
where type can be header, url or param.
Can be used the body message as source? i have to evaluate something like this:
<match type="????" source="json-eval($.codice)" regex="0"/>
where type should the message body. Is it possible? or have i to use the FILTER mediator? i mean something like:
<filter xpath="/codice='OK'">
<then>
//DO SOMETHING
</then>
<else>
DO ANOTHER THING
</else>
</filter>

Couple of things: Match only supports the types header, param and url. You will also not be able to use JSON Path on the match regardless of whether it supports message body.
You should go with filter if you are routing based on message body.

Related

WSO2 ESB validate on empty/missing XML tags

I am trying to make a validation of XML requests on missing or empty XML tags. I used this code
<filter description="Validate material" regex=".+"
source="//E1MARAM[not(MATNR)] | //E1MARAM/MATNR[not(text())]">
<then>
<log category="WARN">
<property name="/material"
value="validation-empty tag MATNR send back to SAP" />
</log>
<property name="HTTP_SC" scope="axis2" type="STRING"
value="500" />
<makefault version="soap11">
<code value="soap11Env:VersionMismatch" xmlns:soap11Env="http://schemas.xmlsoap.org/soap/envelope/" />
<reason value="Missing SAP parameter" />
<detail>MATNR</detail>
</makefault>
<respond />
</then>
</filter>
which beatifically checks the XML tag //E1MARAM/MATNR
My problem is that this works only when the tag is empty.
It seems like the Filter mediator with reqex .+ and xpath //E1MARAM[not(MATNR)] does not meet the condition and thus the check does not work
Any idea why? or perhaps another idea how to better validate in WSO2 ESB on missing XML tags or values without XSD? a XSD schema cannot be used, as the XML request does not have a fixed structure - typical for SAP iDoc
The easiest way is to check for an not empty string ''. This will resolve to false both when empty and when missing. Also, you do not have to use the regex to check, you can just use xpath. If you give the filter mediator an xpath expression it will resolve it as if checking a boolean.
<filter description="Validate material" xpath="not(//E1MARAM/MATNR!=''") >
This will return true if the element is either empty or does not exist. It will return false if there is a text value.

'redirect' and 'proxy' vs 'forward' and 'passthrough' in Tuckey URLRewrite

Note that, in my attempt to display code examples, I will redact/edit out any references to the company for whom I work in an effort to obscure their identity, not so much to hide the fact that I'm even asking. It should also be of note that I am very new to this game of UrlRewrite/Tuckey/dotCMS.
I have been having trouble getting a redirect to work. It's using Tuckey URLRewrite through dotCMS. The attempt is to redirect, but as a forward versus a proxy, for SEO purposes.
I've found that the following works ('redirect' and 'proxy' are interchangeable here):
<to type="proxy">http://[redacted]:8080$1$3?%{query-string}</to>
However, the following leads to a 404 ('forward' and 'passthrough' are interchangeable here):
<to type="forward">http://[redacted]:8080$1$3?%{query-string}</to>
The entirety of the rule is as follows:
<!-- EN with Query Params -->
<rule>
<from>^/([^/]+)/en/([^/]+)?$</from>
<to type="proxy" qsappend="true">[redacted]:8080$1$3&%{query-string}</to>
</rule>
<!-- EN without Query Params -->
<rule>
<from>^(.*)(\/en)(\/.*)?$</from>
<to type="proxy">[redacted]:8080$1$3?%{query-string}</to>
</rule>
Some of my initial questions (as many more are likely to arise):
Is there such a difference between 'proxy'/'redirect' and 'forward'/'passthrough' that more specialized efforts to achieve a meaningful redirect need to be implemented?
Am I missing something in other configuration files that may affect the outcomes of these attempts at redirection?
EDIT: The differences in RegEx are me trying things to see if that could possibly be where the disconnect is occurring
Because urls in dotCMS do not really exist, the servlet requestdispatcher, which is used by forward rules, does not work. You need to set a request attribute, CMS_FILTER_URLMAP_OVERRIDE, which dotCMS will respect. In code, this looks like:
NormalRule forwardRule = new NormalRule();
forwardRule.setFrom( "^/example/forwardDotCMS/(.*)$" );
SetAttribute attribute = new SetAttribute();
attribute.setName("CMS_FILTER_URLMAP_OVERRIDE");
attribute.setValue("/about-us/index");
forwardRule.addSetAttribute(attribute);
addRewriteRule( forwardRule );

WSO2 Routing based on message using XPath

I have a situation where I want to route the incoming request to a proxy based on XPath if present in a message or not.
For example: Let us consider the two request to a proxy.
Request 1:
<PCSDetailProxyResponse>
<MarketDefinitionsRequest>
<![CDATA[Request elements TBD]]>
</MarketDefinitionsRequest>
</PCSDetailProxyResponse>
Request 2:
<PCSDetailProxyRequest>
<ReportParameterRequest>
<![CDATA[Request elements TBD]]>
</ReportParameterRequest>
</PCSDetailProxyRequest>
<endpoint xmlns="http://ws.apache.org/ns/synapse" name="ReportParameterRequestEP">
</endpoint>
<endpoint xmlns="http://ws.apache.org/ns/synapse" name="MarketDefinitionsRequest">
</endpoint>
I want to route the two requests to 2 different end points based on the kind of request ( MarketDefinitionsRequest or ReportParameterRequest).
If the request contains ReportParameterRequest then I want to send to ReportParameterRequestEP
If the request contains MarketDefinitionsRequest then I want to send to MarketDefinitionsRequestEP.
What should I do to identify if a request contains or element because based on that only I will have to take the routing decision?
I recommend using filter mediators for this:
<filter xpath="fn:exists($body/MarketDefinitionsRequest)">
<sequence key="MarketDefnitionsSequence"/>
</filter>
<filter xpath="fn:exists($body/ReportParameterRequest)">
<sequence key="ReportParameterSequence"/>
</filter>
You can then create separate sequences for processing the different scenarios.
If you were looking for the value of the content of a node, then the switch mediator would be easier. Because you're filtering on the name of the node, the exists function is necessary instead.

Parsing Error Response in Camel

New to Camel, and I'm trying to parse a response error xml. Within the camel-context I need to determine if a specific value exists in the error file, and handle it differently than other errors.
The other errors use a series of when statements:
<when>
<xpath>/abc:ErrorResponse/abc:Error/abc:Message/.</xpath>
<setHeader headerName="RESPONSE_STRING">
<xpath resultType="java.lang.String">/abc:ErrorResponse/abc:Error/abc:Message/.</xpath>
</setHeader>
<setHeader headerName="MY_DATA_FIELD"><constant>Error</constant></setHeader>
<to uri="def:doErrorStuff" pattern="InOnly"/>
</when>
<when>
<xpath>/ghi:ErrorResponse/ghi:Error/ghi:Message/.</xpath>
<setHeader headerName="RESPONSE_STRING">
<xpath resultType="java.lang.String">/ghi:ErrorResponse/ghi:Error/ghi:Message/.</xpath>
</setHeader>
<setHeader headerName="MY_DATA_FIELD"><constant>Error</constant></setHeader>
<to uri="def:doErrorStuff" pattern="InOnly"/>
</when>
My error XML file has an outer error element with child "Code" element. I need to parse the value of the code element
UPDATE: HERE IS THE XML I AM PARSING
<ErrorResponse xmlns="http://myhost/location1/">
<Error>
<Type>reserved</Type>
<Code>TEXT_I_NEED_TO_PARSE_IN_WHEN_STATEMENT</Code>
</Error>
<RequestId>some_id</RequestId>
</ErrorResponse>
I used a combination of xpath and 'simple' to make the check. Like this:
<when>
<xpath>/ghi:ErrorResponse/ghi:Error/ghi:Message/.</xpath>
<when>
<simple>${in.body.code} == 'StringIAmSearchingFor'</simple>
<!-- Do Stuff --!>
</when>
</when>
However, I am not getting the response I expect.
1. Is there something wrong with this approach or the syntax?
2. Is there a way to combine the double when layout so they are and-ed together. Otherwise, if I add my "when" statement just ahead of the existing two, the existing "ghi" when statement will never get executed (the xpath statements match).
You are using xpath on your input suggesting that it's XML, then simple (${in.body.code}) which in that case also would be XML. Simple is used to traverse java bodies and not other formats such as XML. Stick to XPATH all the way - your code above can easily be implemented in xpath. Another way, of course, would be to unmarshal the XML into java objects using xstream or jaxb, then you can use only simple/OGNL/groovy or whatnot.
Since I recommend you to solve this very case with xpath alone, you can of course use the xpath and operator to and several xpath expressions together. All logic and power in camel choice/when reside in the expression language you are using (be it simple or xpath), so if you want to mix expression languages, you have to build up sort of a decision tree. That could actually be something good if you are trying to implement very complex routing logic. For a single special case - it's, IMHO, just messy.

Apache Camel: how store variable for later use

while 'playing around' with Camel using Spring DSL, I came across the following problem. Suppose the expected message flow looks like this:
client sends HTTP POST message with XML body to CAMEL
CAMEL proxies HTTP POST message towards server, with the URI slightly adapted using
info from the received XML body (eg: use XPATH to filter out a certain parameter)
after CAMEL has received a reply, CAMEL sends HTTP PUT message towards server, using parameters out of the XML body received in 1
So something like:
<route>
<from uri="...">
<to uri="...">
<to uri="...">
</route>
Question: how do I store the parameters in Spring DSL in step 1, so that I can use them later in step 3 ?
So, I would like to extract XML parameters out of the XML body of the message received in step 1 and put them into variables, which I then later on can use to compose the message to be sent in step 3.
For extracting the parameters, I was thinking of using XPATH. That looks ok, but I just don't see how to put the output of the XPATH into a variable and then use that variable later on ... (syntax ??)
Note: as you can see, my development knowledge is rather limited ... sorry for that. But it would still be great if someone could help with this :).
you can set store data in the Exchange properties or message headers like this...
.setHeader("ID", XPathBuilder.xpath("/order/#id", String.class))
.setProperty("ID", XPathBuilder.xpath("/order/#id", String.class))
and then retrieve them in a bean/processor from the Exchange like this...
String propId = (String) exchange.getProperty("ID");
String headerId = (String) exchange.getIn().getHeader("ID"); }
I leave you some examples:
<setHeader headerName="token">
<constant>someValue</constant>
</setHeader>
<setHeader headerName="userName">
<simple>${properties:userName}</simple> //from config
</setHeader>
<setProperty propertyName="bodyBkp">
<simple>${in.body}</simple>
</setProperty>
<setProperty propertyName="orderNumber">
<xpath resultType="String">//item[1]/orderNumber/text()</xpath>
</setProperty>
Getter
${exchangeProperty[orderNumber]}
${in.headers.token}
Documentation
Check the simple expression language:
http://camel.apache.org/simple.html
Sometimes looking at the test cases of Camel can be helpful as well, in particular for Spring DSL:
setProperty with Spring DSL
setHeader using XPATH with Spring DSL
simple expression language test

Resources