XQuery transformation with WSO2 ESB - wso2

I am designing a Proxy Service sequence that includes an XQuery transformation. I have a problem with referencing the registry file containing the transformation.
Here is the sequence:
<sequence name="MySequence" xmlns="http://ws.apache.org/ns/synapse" >
<xquery key="conf:/wsdl/xqueryRequest.xq"
target="..."
xmlns:ns="http://org.apache.synapse/xsd" >
<variable xmlns:ns2="http://..." name="var1" expression="..." type="ELEMENT" />
</xquery>
<send>
<endpoint>...</endpoint>
</send>
</sequence>
The file containing the XQuery transformation is uploaded in /_system/config/wsdl/xqueryRequest.xq
And this is the exception I am getting:
WARN ERROR_DETAIL : org.apache.synapse.SynapseException:
Unable to execute the query at
org.apache.synapse.mediators.xquery.XQueryMediator.handleException(XQueryMediator.java:627) at
org.apache.synapse.mediators.xquery.XQueryMediator.mediate(XQueryMediator.java:130) at
org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:60) at
...
Caused by: java.lang.NullPointerException at
org.wso2.carbon.mediation.registry.WSO2Registry.lookup(WSO2Registry.java:177) at
org.apache.synapse.registry.AbstractRegistry.getResource(AbstractRegistry.java:63) at
org.apache.synapse.config.SynapseConfiguration.getEntry(SynapseConfiguration.java:693) at
org.apache.synapse.core.axis2.Axis2MessageContext.getEntry(Axis2MessageContext.java:194) at
org.apache.synapse.mediators.xquery.XQueryMediator.performQuery(XQueryMediator.java:233) at
org.apache.synapse.mediators.xquery.XQueryMediator.mediate(XQueryMediator.java:123)
... 11 more
The exception shows a NullPointer at WSO2Registry.lookup so I assume that the problem is in finding the XQuery file in the registry, this part:
key="conf:/wsdl/xqueryRequest.xq"
The documentation shows two code snippets(390 and 391) with XQuery transformation but non of them explains howto reference the XQuery file.
Question: What should be the correct value for the key parameter? Do I need to use the "Local Entry" feature? If yes, then should I define the value as "Inline XML Entry" or "Inline Text"?
UPDATE 03/23/12:
Question 2: Perhaps a simpler question: Where should I copy/upload the xqueryRequest.xq file when I set Xquery mediator's key field to key="xqueryRequest.xq"?

Can you try saving your xquery as a local entry and refer it from the XQuery mediator.
(Please have a look at local entry samples)

Related

Accessing XML attributes in WSO2 EI

I'm able to access the body of the payload and other Childs of the body but I'm not able to access the attributes defined inside the xml tag i.e.
<data version="2.0.0_461" timestamp="2022-09-02T15:56:37+00:00Z" instance="stg" host="37432d6e1ea8">
<type id="1019275" name="HP Color LaserJet MFP M477fdw">
<name firstName="1" lastName="Hewlett Packard"/>
<capability id="2" name="Yellow"/>
</type>
<cons>
<con name="Black" id="103">
<dataSource>RM</dataSource>
<colors>
<color name="Black" id="3" order="1"/>
</colors>
</con>
</cons>
</data>
In the above xml I can access the capability with $body//data//type//capability it give me <capability id="2" name="Yellow"/> but I want to access the name defined attribute of capability.
How can I do that. I'm using WSO2 EI 6.6.0
You can use # symbol to access the attributes in Xpaths. So using $body/data/type/capability/#name will return the value of name attribute.
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="test"
startOnLoad="true"
statistics="disable"
trace="disable"
transports="http,https">
<target>
<inSequence>
<log level="custom">
<property expression="$body/data/type/capability/#name" name="Value"/>
</log>
<respond/>
</inSequence>
</target>
<description/>
</proxy>
If you send the payload to the above proxy as a request, you will be able to see the log mediator output as below in the logs.
[2022-09-02 20:53:02,976] INFO {org.apache.synapse.mediators.builtin.LogMediator} - Value = Yellow
Dils' answer is correct to access the attribute. Let me add more details, the syntax used for data extraction from XML payloads is not something invented by WSO2 or not something specific to WSO2. WSO2 EI simply supports Xpath 1.0 and Xpath 2.0 expressions. Simply when you say $body/data/type/capability WSO2 will run the XPATH expression /data/type/capability on the value assigned to $body variable(In your case request payload). So you can use any Xpath expression to extract data from your payload. You can learn more about Xpath expressions from here. You can test your Xpath expressions on an online evaluator like this.
The Xpath 1.0 language specification is here. Xpath 2.0 language specification is here. Here are a few different Xpath expressions to extract the value yellow.
/data/type/capability/#name
//capability/#name
//type/capability/#name
//type[#name = 'HP Color LaserJet MFP M477fdw']/capability/#name
//capability/#*[2]

replace function with get-property in wso2esb

I am trying the below option and i m getting error, can anyone suggest me the solution. I have added synapse.xpath.dom.failover.enabled=true
Code:trying to replace ~TOKEN~ with the property value
<property name="verificationLink" expression="fn:replace($ctx:reqVerifyUrl , '~TOKEN~', get-property('verification_code'))" scope="default" type="STRING" xmlns:fn="http://www.w3.org/2005/xpath-functions" />
Error:
TID: [-1234] [] [2017-02-15 00:14:19,318] ERROR {org.apache.synapse.util.xpath.SynapseXPath} - Evaluation of the XPath expression fn:replace($ctx:reqVerifyUrl , '~TOKEN~', get-property('verification_code')) resulted in an error {org.apache.synapse.util.xpath.SynapseXPath} net.sf.saxon.trans.XPathException: Unknown system function get-property()
get-property is not a standard xpath function and you must say to the xpath engine that this function comes from synapse :
<property name="verificationLink" expression="fn:replace($ctx:reqVerifyUrl , '~TOKEN~', syn:get-property('verification_code'))" scope="default" type="STRING" xmlns:fn="http://www.w3.org/2005/xpath-functions" />
You do not need to add the definition of 'syn' namespace, it is well known in your mediation (xmlns:syn="http://ws.apache.org/ns/synapse")
Two things need to be done:
A. Review this and ensure your Synapse config is set correctly. Is there any replace function in wso2esb?
B. Then you need to add prefix fn & syn if you need to use methods like get-property() with XPath 2.0. Also note, you must use (include) the following namespaces values for ‘syn’ and ‘fn’.
xmlns:syn=”http://ws.apache.org/commons/ns/payload”
xmlns:fn=”http://www.w3.org/2005/xpath-functions”
Here is a sample property mediator using replace.
<property xmlns:syn="http://ws.apache.org/commons/ns/payload" xmlns:fn="http://www.w3.org/2005/xpath-functions" name="xmlValue" expression="fn:replace(syn:get-property('textValue'), 'xmlData=', '')></property>;

WSO2 ESB 4.8.1 Switch Mediator Case matching not working

I am using WSO2 ESB 4.8.1. I need to check if a particular field exists in the Incoming Payload XML. If Iit does, a Switch Case should run, otherwise it should run a default scenario. The field on which I am checking will always have a dynamic value and it would look like following:
20000569899
I wrote following logic in ESB:
<property name="CheckIdExist" expression="//*[local-name()='Id']" scope="default" type="STRING" description="CheckIdExist"/>
<switch source="get-property('CheckIdExist')">
<case regex="[a-zA-Z0-9]">
<sequence key="SequenceA"/>
<sequence key="SequenceB"/>
<sequence key="SequenceC"/>
</case>
<default>
<log></log>
</default>
</switch>
Problem:
The problem is that Switch is able to pick a value from the property but it does not match the Case regular expression. Following are some ESB Logs Entries:
Logs Entries:
XPath : get-property('CheckIdExist') evaluates to : 20001089900
None of the switch cases matched - executing default
I checked online, this regular expression works. So what i am unable to understand is that why WSO2 ESB is not recognizing it as a valid expression. Or is there any other way to check that if a field exists in an input request then a particular switch case should work, Otherwise not.
Your regular expression lacks a quantifier + meaning 1 or more occurrences:
<case regex="[a-zA-Z0-9]+">

WSO2 ESB Collout address from Property or XPath-expression

I have the config with development and production sections. This sections contain the URLs of backends. In my inSequence i need it to Callout to these backends several times per request.
<config>
<env>prod</env>
<backend env="prod">http://localhost:1234/</backend>
<backend env="dev">http://localhost:2345/</backend>
</config>
I read this config from Local Entry (as XML) and want to set Callout's URL as an Property.
I don't want to hardcode these backends inside my code with "Switch" statement, because it's possible to use more than two environments.
Could you please show me an example?
Thank you.
You can read xml file in registry. Simply define property of OM type like this:
<property name="test" expression="get-property('registry','conf:/test.xml')" scope="default" type="OM" />
Then you can see the value by logging like this:
<log level="custom"> <property name="test.b" expression="$ctx:test//b" /> </log>
And in the xml file that you have put in the root of registry, you would fill it like:
<a>Hello<b>WSO2</b></a>
I have learned it from this link.
I found the answer. According to source of Callout mediator:
CalloutMediator.java
It uses "To" header if URL is not specified.

WSO2 Enrich Mediator

[WSO2 ESB V4.5.0]
What is wrong with how I'm configuring the enrich mediator to accumulate XML? I have a sequence of n PojoMediators that retrieve XML from a database with each setting a context property with the XML represented as a string. For example, after the first PojoMediator executes, its' context property is set to:
customerInformation = <cust><id>1</id><oc></oc><ca>0</ca></cust>
and I'm trying to enrich the body with that XML content but end up with:
[snip]
</header>
<cust><id>1</id><oc></oc><ca>0</ca></cust></root></soapenv:Body></soapenv:Envelope> {org.apache.synapse.mediators.builtin.LogMediator}
..where the enrich mediator is escaping the referenced "custInfo" XML. My enrich configuration is:
<enrich>
<source type="property" property="custInfo"/>
<target type="body"/>
</enrich>
Is there a means to coerce the enrich mediator to treat the property ("custInfo") as an XML fragment rather than as straight text? I'm assuming that this is why the XML is getting escaped as the mediator believes it is setting the content of a node rather than specifying an XML fragment.
How you defined property ? Can you try after adding
type="OM"
to the property definition and try again?