wso2 xpath expression in property mediator doesn't work - eclipse

I am trying to populate a property in a WSO2 proxy. I'am using the following syntax and xpath expression:
<property expression="//RelationValueList/PersonnelRelationValueUnitType[RelAttrId='R54' and DateTo=max(//RelationValueList/PersonnelRelationValueUnitType[RelAttrId='R54']/DateTo/xs:dateTime(.))][last()]/RelationValue" name="RelValue" scope="default" type="STRING"/>
This Xpath expression is working fine in an online Xpath tester. But when using it in WSO2 expression of a property mediator it gives me the following Eclipse error:
wso2 unknown synapse configuration tag
Error message
The XML document looks like this:
<GetPersonnelResponse>
<GetPersonnelResult>
<RelationValueList>
<PersonnelRelationValueUnitType>
<RelAttrId>C1</RelAttrId>
<RelationValue>1234</RelationValue>
<DateFrom>1900-01-02T00:00:00</DateFrom>
<DateTo>2199-12-31T00:00:00</DateTo>
</PersonnelRelationValueUnitType>
<PersonnelRelationValueUnitType>
<RelAttrId>R54</RelAttrId>
<RelationValue>GEN123</RelationValue>
<DateFrom>1900-01-02T00:00:00</DateFrom>
<DateTo>2017-12-04T00:00:00</DateTo>
</PersonnelRelationValueUnitType>
<PersonnelRelationValueUnitType>
<RelAttrId>R54</RelAttrId>
<RelationValue>GEN456</RelationValue>
<DateFrom>2017-12-05T00:00:00</DateFrom>
<DateTo>2099-12-31T00:00:00</DateTo>
</PersonnelRelationValueUnitType>
</RelationValueList>
</GetPersonnelResult>
</GetPersonnelResponse>
Xpath 2.0 is enabled in WSO2esb.
I need to select the RelationValue with the highest DateTo value. If there are multiple values, I take the last one.
Anyone knows how to fix this?

You use namespace xs: in your expression. You need to define it in top parent tag of it mediator.

Related

ZOQL Execution via Zuora REST API

I am trying to execute some ZOQL via Zuora REST API.
I've referred this doc and I am using REST endpoint v1/action/query to execute ZOQL.
First I tried with very simple request and got the result back
{
"queryString": "select AccountId, FirstName, LastName from contact"
}
Now I tried query with asterisk like below
{
"queryString": "select * from contact"
}
But I got below error
{
"faultcode": "fns:MALFORMED_QUERY",
"faultstring": "You have an error in your ZOQL syntax",
"detail": {
"MalformedQueryFault": {
"FaultCode": "MALFORMED_QUERY",
"FaultMessage": "You have an error in your ZOQL syntax"
}
}
}
From here, I found that ZOQL supports asterisk. I even got the same error for ZOQL which involves multiple objects. Like
SELECT Subscription.Name, Account.Name FROM Subscription WHERE Subscription.Status='Active' AND DefaultPaymentMethod.CreditCardType='Visa'
EDIT
Above query does not work in Zuora SOAP API as well
How can I execute query with asterisk in Zuora REST API or in Zuora SOAP API?
Queries With Asterix In ZOQL:
In short: You just can't use asterix.
More info:
From Zuora KnowledgeCenter:
No Wild Card Support
You cannot use the asterisk wild card (*) for field names with a
query() call. You must explicitly specify a field name.
The above source you mentioned stating that you can use asterix, is NOT about ZOQL, but about Export ZOQL.
Export ZOQL is different from ZOQ, as stated in the docs above:
Zuora Export ZOQL (Zuora Object Query Language) is the query language
used to create Exports with the Export object in the Zuora SOAP API.
Zuora Export ZOQL is similar to our general ZOQL, with a few
differences. The biggest difference is that with Exports, you query a
Zuora data source, not a SOAP API object.
Hope this helps you.
Good luck!
When you use a * in query it is because:
1) you want all the fields available
OR
2) you want to find out WHAT fields are available.
For the later case, use the Describe function of the REST service as in:
https://{servicename}.zuora.com:####/v1/describe/Invoice
which will return an XML description of the Invoice (or any other) object as:
<?xml version="1.0" encoding="UTF-8"?>
<object href="https://services470.zuora.com/apps/api/describe/Invoice">
<name>Invoice</name>
<label>Invoice</label>
<fields>
<field>
<name>AccountId</name>
<label>Account ID</label>
<selectable>true</selectable>
<createable>true</createable>
<updateable>false</updateable>
<filterable>true</filterable>
<custom>false</custom>
<maxlength></maxlength>
<required>true</required>
<type>text</type>
<contexts>
<context>soap</context>
</contexts>
</field>
<field>
<name>AdjustmentAmount</name>
<label>Adjustment Amount</label>
<selectable>true</selectable>
<createable>false</createable>
<updateable>false</updateable>
<filterable>true</filterable>
<custom>false</custom>
<maxlength></maxlength>
<required>true</required>
<type>decimal</type>
<contexts>
<context>soap</context>
<context>export</context>
</contexts>
</field>
<!-- All fields for Invoice...ETC -->
</fields>
</object>

How to invoke a formhandler using ATG REST Client

I'm trying to invoke ProfileFormHandler's create handle using ATG rest client as shown below.
mSession = RestSession.createSession(mHost, mPort,"kim#example.com","password");
mSession.setUseHttpsForLogin(false);
mSession.login();
Map<String,Object> params = new HashMap<String,Object>();
params.put("value.login", "buddha#oracle.com");
params.put("value.email", "buddha#oracle.com");
params.put("value.password", "password");
RestResult result = RestComponentHelper.executeMethod("/atg/userprofiling/ProfileFormHandler","create",null,params,mSession);
I'm getting form exceptions that says, I'm not passing Login and Password Fields.
["Missing value for the required property Password",
"Missing value for the required property Login name"]
I've tried all combinations of login and password fields like value.login, Login, login, value.Login etc., but nothing seemed to work. All combinations giving the same form exceptions.
How do I invoke an ATG form handler using ATG REST Client and pass parameters to it?
Definitely need more information but looking at your code I can see that you have a value.login which is not configured ootb and believe this is causing the NPE. Assuming you have not customized the ootb ATG RegistrationFormHandler and the required field in the repository the only values you need to pass to the form handler are:
value.email
value.password
value.confirmPassword
value.firstName
value.lastName
Also, the help is specific that the data-type of the value property needs to be java.util.Dictionary
Add the following to /atg/rest/security/restSecurityConfiguration.xml
<resource component="/atg/userprofiling/ProfileFormHandler" secure="false">
<method name="handleCreate" secure="false">
<acl value="EVERYONE:read,write,execute" />
</method>
<property name="value.login" secure="false" />
<property name="value.password" secure="false" />
</resource>

WCS7 best practice to receive certain catalog entry information?

[WCS 7, FixPack 7, Feature Pack 6]
I need to generate a feed with certain catalog entry (product) information such as name, image(s), category, price, seo-url, descriptive attributes and so on.
To generate this feed i will use the scheduler framework and created a controller command which will be invoked after a certain time has passed.
Now i need to receive the catalog entry data of each item in a specific store/catalog.
As far as i know there are several ways to achieve this:
Access Beans
SOA (new Access Profile with specific SQL)
I tried to use Access Beans to get all necessary information but I got stuck with seo-url, price etc.
Are there more ways and what is the best practice to get a specific set of catalog entry attributes?
I suggest you study/investigate in your WCS Development environment how site map generation schedule command is implemented (SitemapGenerateCmd) and how it is calling the JSP template file (sitemap.jsp)
you need to modify a bit in your command to create a jsp template for your feed and call that template from your scheduler command you've created .
calling template command for messaging system, make sure to use following properties in ActionForward tag to register the JSP for messaging from back-end:
example:
<forward className="com.ibm.commerce.struts.ECActionForward"
name="SitemapIndexView" path="/SitemapIndex.jsp">
<set-property property="direct" value="true"/>
<set-property property="resourceClassName" value="com.ibm.commerce.messaging.viewcommands.MessagingViewCommandImpl"/>
<set-property property="interfaceName" value="com.ibm.commerce.messaging.viewcommands.MessagingViewCommand"/>
<set-property property="properties" value="storeDir=no"/>
<set-property property="implClassName" value="com.ibm.commerce.messaging.viewcommands.MessagingViewCommandImpl"/>
</forward>
then the logic for extracting data from your product/catalog beans will be handled inside the JSP and you can easily form the output data as you want (XML, CSV, JSON .. etc)
the advantages and benefits of using this way are you can leverage Commerce Server OOTB JSTL tags , WCF tags for retrieving all information and using wcf:url for SEO URLS OOTB even you can call BOD/SOA commands using <wcf:getData tag and finally your will get more structured design that can easily maintain and reuse in future .
sitemap.jsp is a good resource for you how to iterate through catalog and sub-catalog to extract product info.
hope that those help you find your solution. need some search and understanding of existing sitemap generation utility .
Thanks.
Abed

WSO2 - Set a property and write it in the Carbon Log

I've created a Custom Proxy and added a class mediator and log Mediator in it. I'm trying to set a property's value in the java class and need to write that in the log, as the proxy gets deployed. But, so far, haven't got any success.
I've tried adding a parameter in the Log mediator and used the get-property() method but it still doesn't print it. If I use a 'Property' mediator itself, then I'm able to write the value in the log but that's not our purpose here.
I've also tried using log.debug in the java class, just to write the usual 'entering/exiting a function', but to no respite.
Could anyone please help?
How are you setting a property in the java class(ie: in your class mediator)?
It should be like;
synapseMesssageContext.setProperty(key,value);
Then,In the sequence flow access it as;
<property xmlns:ns="http://org.apache.synapse/xsd" name="testing the property"
expression="get-property('key')" scope="default"/>
You can use log.info to print any log messages. Please reffer [1] which has logged messages using log.info.
[1]http://wso2.org/library/2898

WSO2 Synapse: setting a URL parameter

I am trying to do something that seems straightforward but can't get it to work. Basically I want the WSO2 API manager to add a URL parameter to a REST call.
Setup and Problem
I have a WSO2 API manager installed. I also have a Tomcat running with a bogus servlet called someservlet that simply logs anything it receives and returns ok. I have added the servlet as an API in the manager, so I can either call the servlet directly or via WSO2 API mgr.
I can run
curl http://localhost:8080/someservlet/servlet/toto?blob=blib&secret=pass
and the servlet works fine, it tells me it's received the path /toto and parameters blob and secret.
I can run
curl -H "Authorization: Bearer [...]" --url "http://192.168.23.1:8280/someservlet/1.0/toto?blob=blib&secret=pass"
And it does exactly the same. So far, so good.
What I want is to run:
curl -H "Authorization: Bearer MqVQuHqLNphtPV3XF1CtXVmbyP8a" --url "http://192.168.23.1:8280/someservlet/1.0/toto?blob=blib"
(note that I've removed the secret parameter)
...and still get the same result.
So basically I want API manager to add the URL parameter secret=pass.
First thing I tried: property mediator
Use Synapse XML config with property REST_URL_POSTFIX.
I edited the API config file, and added
<property name="REST_URL_POSTFIX" value="/blob?toto=titi" scope="axis2" type="STRING"/>
Now if I run
curl -H "Authorization: Bearer [...]" --url "http://192.168.23.1:8280/someservlet/1.0/toti?blab=blib&secret=puss"
it's as if I ran someservlet/1.0/blob?toto=titi: all my path and parameters have disappeared and been repaced with the configured ones. Hey, that's how it's supposed to work, isn't it!
Problems:
this doesn't add something to the URL, it sets the URL postfix, meaning that existing parameters disappear (in the above example, blab=blib)
it has to start with a "/" to be a valid value, so I can't just add &secret=pass (of course, because of problem 1, this would be useless anyway)
So basically this doesn't enable me to append the final &secret=pass.
Second thing I tried: rewrite URL mediator
I found this mediator, and although it probably won't do the trick, it's a good lead: I can just call with secret=foo, and get the mediator to replace it with secret=pass.
I put this in the config file:
<rewrite>
<rewriterule>
<action type="replace" value="pass" fragment="query" regex="foo"/>
</rewriterule>
</rewrite>
This doesn't work. At first I thought I didn't have the action parameters right. But the error message is:
Malformed URL when processing /someservlet/1.0/toti?blab=blib&secret=foo
Malformed? There's more detail in the exception stack trace:
java.net.MalformedURLException: no protocol: /someservlet/1.0/toti?blab=blib&secret=foo
So what's happening is that the mediators (log or rewrite) receive a message whose "To:" field points to a URL with no protocol!
Of course I've been googling around, and there are some cases where I find other people have logMediator: To: /blabla, and other (most) cases where they have logMediator: To: http ://blabla. I don't really see what's causing the difference. :-(
So this is where I'm stuck!! :-(
Option to be tried
I'm aware that there's probably a sledgehammer solution that should work:
use property to store the full path and all parameters
implement my own mediator (e.g. in Java) to modify these parameters
use property REST_URL_POSTFIX to put the modified postfix on the call
However I feel that this problem should have a simpler solution.
I have a kind of hope that someone will point me to a simple resource (mediator, sample, syntax error, anything) that I haven't found and that does just what I want. Optimism... :-)
Thanks for reading. Any ideas?
As i understood, you are trying to append the secret=pass to your endpoint url.
When you invoke the API , i belive you are sending that parameter.
Same time you are sending "blab=blib" parameter also. But in the ESB you need to change that to "toto=titi"
The method you used is right.(ie: Using property REST_URL_POSTFIX) In that case it will replace all requets parameter.
But before using that, you can save the request parameter and using the "REST_URL_POSTFIX"
you can achive the final REST url you need. (yes, that is the final option you mentioned as "to be tried")
In the "TO" address, you will only have address after port number.
If you use "" POST_TO_URI" property yopu will see the full adress URL printed in the log, but we use that if there is any proxy server configured between BE service and ESB
I've solved my problem.
Here's what I do:
in the config file, get the URL postfix using REST_URL_POSTFIX and
put it in a property
edit the property in a Java mediator
use REST_URL_POSTFIX to set the new postfix in XML
For the 1rst step, I use this line:
<property name="querystrings" expression="get-property('axis2', 'REST_URL_POSTFIX')"/>
this took some time to corner, because there are many lines out there that don't work for me, it took the 2 parameters (axis2 and REST...) to get it straight.
For the second step, this is the config XML:
<class name="mypackage.AddUrlParamMediator">
<property name="paramName" value="mykey"/>
<property name="paramValue" value="mysecret"/>
</class>
this is the mediator class (without imports):
public class AddUrlParamMediator extends AbstractMediator {
private String paramName = "default";
private String paramValue = "default";
public void setParamName(String paramName) {
this.paramName = paramName;
}
public void setParamValue(String paramValue) {
this.paramValue = paramValue;
}
public boolean mediate(MessageContext synapseMsgContext) {
SynapseLog log = this.getLog(synapseMsgContext);
String urlNewParam = this.paramName + "=" + this.paramValue;
Object queryStringsPpty = synapseMsgContext.getProperty("querystrings");
if (queryStringsPpty == null) {
log.error("### queryStringPpty=null, exiting!");
return true;
}
String queryStrings = queryStringsPpty.toString();
queryStrings = (queryStrings.contains("?"))
? queryStrings + "&" + urlNewParam
: queryStrings + "?" + urlNewParam;
synapseMsgContext.setProperty("querystrings", queryStrings);
return true;
}
}
and of course here's the third step in the XML config:
<property name="REST_URL_POSTFIX" expression="get-property('querystrings')" scope="axis2" type="STRING"/>
So all this basically sets a parameter at the end of the URL.
Hope this helps others.
For anyone who may have the same issue, here's another solution, simpler and works.
Go to the carbon admin portal, to the list of APIs, find the relevant API and click on it.
This leads to the XML config of the API.
After the "address" field (and at the same level in the XML) add the field:
<property name="Authorization" value="stuff to add" scope="transport"/>
This adds the property "Authorization" with value "stuff".