Event builder XML mapping in WSO2CEP 3.0.0 - wso2

Lets say, a stream named inputStream is defined with attributes name:string, surname:string, address:string. For this stream, if an event builder is defined like the following,
<property>
<from xpath="xpathForSurname"/>
<to default="NULL" name="surname" type="string"/>
</property>
<property>
<from xpath="xpathForName"/>
<to default="NULL" name="name" type="string"/>
</property>
<property>
<from xpath="xpathForAddress"/>
<to default="NULL" name="address" type="string"/>
</property>
When I send an input like ('John', 'Lennon', 'Liverpool') I expect inputStream to be ['John', 'Lennon', 'Liverpool'], but the result stream is ['Lennon', 'John', 'Liverpool']. The reason is that values of the attributes are added to stream following the mapping sequence in builder definition.
Therefore, <to> tags in definition becomes pointless (the value upon xpathForSurname evaluation is not mapped to surname but name). Is this a bug or is it done on purpose?

Yes, this seems to be a bug in CEP 3.0.0 and will be fixed in a future release. I have created a JIRA with the information you provided in CEP-640.
For now, the workaround would be to let the input stream come directly as it is via the event builder without reordering the attributes and doing any manipulations to the ordering at the level of execution plans. Hope this workaround will work for you.

Related

Hybris Custom WSDTO on hybris product data

Hi I had created eProductForm bean in the commerecefacades-beans.xml I added custom attribute of ProductData.
<bean class="de.hybris.platform.commercefacades.product.data.ProductData">
<property name="eProductForm" type="String"/>
</bean>
then in commercewebservice-beans.xml, I added the custom attribute of ProductWsDTO
<bean class="de.hybris.platform.commercewebservicescommons.dto.product.ProductWsDTO">
<property name="eProductForm" type="String"/></bean>
from SearchResultProductPopulator populated productdata of eProductForm from my search result.
target.setEProductForm(this.<String> getValue(source, "E_PRODUCT_FORM"));
PFB
dto mapping
<bean parent="fieldSetLevelMapping" id="productWsDTOFieldSetLevelMapping">
<property name="dtoClass" value="de.hybris.platform.commercewebservicescommons.dto.product.ProductWsDTO"/>
<property name="levelMapping">
<map>
<entry key="BASIC"
value="purchasable,stock,name,baseProduct,availableForPickup,code,url,price"/>
<entry key="DEFAULT"
value="summary,averageRating,purchasable,stock(DEFAULT),description,variantMatrix(DEFAULT),name,baseOptions(DEFAULT),baseProduct,availableForPickup,variantOptions(DEFAULT),code,url,price(DEFAULT),numberOfReviews,manufacturer,categories(BASIC),priceRange,multidimensional,configuratorType,configurable,tags"/>
<entry key="FULL"
value="summary,productReferences(FULL),classifications(FULL),averageRating,purchasable,volumePrices(FULL),variantType,stock(FULL),description,variantMatrix(FULL),name,baseOptions(FULL),baseProduct,availableForPickup,variantOptions(FULL),reviews(FULL),code,url,price(FULL),numberOfReviews,manufacturer,volumePricesFlag,futureStocks(FULL),images(FULL),categories(FULL),potentialPromotions(FULL),priceRange,multidimensional,configuratorType,configurable,tags,eProductForm,ePickledGroup"/>
</map>
</property>
</bean>
Below is the code I am calling Mapper.. While I debugged my code sourceresult is having product data of that custom attreibute. But I am not getting the eproductform in the WSDTO response.
final ProductSearchPageData<SearchStateData, ProductData> sourceResult = searchProducts(query, currentPage, pageSize, sort);
if (sourceResult instanceof ProductCategorySearchPageData)
{
return getDataMapper().map(sourceResult, ProductCategorySearchPageWsDTO.class, fields);
}
But in logs I see:
[EL Warning]: 2019-02-20 18:31:27.341--Ignoring attribute
[eProductForm] on class
[de.hybris.platform.commercewebservicescommons.dto.product.ProductWsDTO]
as no Property was generated for it.
As #Farrukh Chishti commented, the URL that you used probably used the DEFAULT level, which doesn't contain the attribute you added. For testing purposes, you can try to add the attribute to BASIC, DEFAULT, and FULL.
In the URL, you can specify the level, something like this:
https://localhost:9002/rest/v2/custom_site/stores?&fields=FULL

WSO2 ESB. Accessing Secure Vault programmaticaly

I am implementing handler for REST API in Java (org.apache.synapse.rest.Handler interface). And there is a case, when I need to access Secure Vault and get a value.
I know that you are able to achieve this by expression="wso2:vault-lookup('YOUR.KEY.HERE')" in sequence, but can't find api to do this in handler. I believe that org.apache.synapse.MessageContext can help, but not sure how.
You can use below code segment in the custom handler.
public String getSecretPassword(String alias, MessageContext messageContext){
RegistrySecretRepository regRepo = new RegistrySecretRepository();
regRepo.setSynCtx(messageContext);
return regRepo.getSecret(alias);
}
Dependency for pom.xml, the version needs to be changed according to your product version.
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.mediation.security</artifactId>
<version>4.2.0</version>
</dependency
Please refer - http://malantech.blogspot.com/2016/10/basic-authentication-handler-with.html
Thanks
I believe you will not be able to get the value of the security vault directly from your handler so I advise you to recover the password and put it in a property and inside your handler to retrieve the property.
<property name="passwordvault"
expression="wso2:vault-lookup('YOUR.KEY.HERE')"
scope="default"/>
And use the MessageContext to get the propertie like this:
context.getProperty("passwordvault");
That's just a workaround which is not advisable , i believe you can try below code as i have used similar earlier as well and it worked
<property expression="wso2:vault-lookup('ei.training.userid')" name="UserID" scope="default" type="STRING"/>
<log>
<property expression="wso2:vault-lookup('ei.training.userid')" name="UID"/>
</log>
And I will answer my own question.
I've created a dummy sequence and placed it into Registry
<sequence name="SecureVaultSeq" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<property expression="wso2:vault-lookup('MY.PASS')" name="NAME"
scope="default" type="STRING"
xmlns:ns="http://org.apache.synapse/xsd" xmlns:ns3="http://org.apache.synapse/xsd"/>
</sequence>
Then in my handler i retrieved it like this:
messageContext.getConfiguration().getSequence("conf:Resources/sequences/SecureVaultSeq.xml").mediate(messageContext);
key = (String) messageContext.getProperty("NAME");
Hope this will help someone.

WSO2 API manager prototype API HTTP response status

I am using the inline javascript prototype feature in the WSO2 API manager and I'm trying to set different HTTP response statuses. Is this possible? If so how is it done?
So far I have tried setting the HTTP_SC property but this doesn't seem to have any effect.
mc.setProperty('HTTP_SC', "404");
I had the same requirement and after much exploring under the hood was able to find a workable solution.
The reason why setting the property:
mc.setProperty('HTTP_SC', "404");
didn't work is that the property needs to be set in the axis2 scope (as Abimaran said). mc.setProperty doesn't set it on that scope. Moreover, the MessageContext object doesn't provide a way to set the scope.
The 'Deploy as Prototype' action actually creates the API definition file by merging the specified in-line script into the a velocity template and storing the resulting API definition into a file.
Template: ./repository/resources/api_templates/prototype_template.xml
Output location: repository/deployment/server/synapse-configs/default/api/
The output file will have a name in the format:
provider--API Name-vVERSION.xml
where provider appears to be the username of the API creator.
What I did was add a filter to the template:
<filter source="boolean(get-property('HTTP_SC'))" regex="false">
<then>
<property name="HTTP_SC" value="200" scope="axis2"/>
</then>
<else>
<property name="HTTP_SC" expression="get-property('HTTP_SC')" scope="axis2"/>
</else>
</filter>
I added it immediately after a similar block (for handling CONTENT_TYPE) at the start of the inSequence element.
You need to add following properties before <send/> mediator
<header name="To" action="remove"/>
<property name="RESPONSE" value="true"/>
<property name="HTTP_SC" value="403" scope="axis2"/>

How to create Property array in wso2 ESB?

I have my request body as:
<tns:InputRequest xmlns:tns="http://tempuri.org/">
<tns:ID>ID_001</tns:ID>
<tns:ID>ID_002</tns:ID>
<tns:Description>Description for ID_001</tns:Description>
<tns:Description>Description for ID_002</tns:Description>
</tns:InputRequest>
and to get the value of ID and Description, i Have created property as:
<property xmlns:tns="http://tempuri.org/" name="ID" expression="//tns:ID" scope="default" type="STRING"/>
<property xmlns:tns="http://tempuri.org/" name="Description" expression="//tns:Description" scope="default" type="STRING"/>
But this gets me only one value. How can i make a property array so that i can store multiple values of ID and description in it and how to retreive from this array property?Looking forward to your reply.Thanks in advance
You should be able to extract those values using XPATH (//node/child::node()) and then set to property.
Below thread will help you to extract required nodes and set to property. You need to set the type as 'OM' to preserve XML as it is.
how to catch an array of nodes to a property

XSLT - Accessing Key's by index - For example, in Muenchian Grouping

<listings>
<property rln="r317080" firm="f102" agent="a2140">
<street>2638 Maple Avenue</street>
<city>Padua</city>
<state>WI</state>
<zip>53701</zip>
<price>229000</price>
<style>2 Story Contemporary, Transitional</style>
<sqfeet>2328</sqfeet>
<bathrooms>2 1/2</bathrooms>
<bedrooms>4</bedrooms>
<garage>2 car, attached</garage>
<age>22</age>
<description>Very nice home on a one block dead end street with woods nearby.
Very special location for quiet and privacy! Home features open floor plan with
large rooms - new patio doors to pretty yard. updates: shingles, vinyl siding,
refrig and dishwasher, garage door. Fireplace in family room flanked by great
built-ins. add first floor laundry and award winning Padua schools.
</description>
</property>
<property ...>
<city>Broxton</city>
...
</property>
<property ...>
<city>Cutler</city>
...
</property>
<property ...>
<city>Argyle</city>
...
</property>
<property ...>
<city>Stratmore</city>
...
</property>
<property ...>
<city>Padua</city>
...
</property>
<property ...>
<city>Oseola</city>
...
</property>
<property ...>
<city>Fenmore</city>
...
</property>
<property ...>
<city>Cutler</city>
...
</property>
<property ...>
<city>Padua</city>
...
</property>
<property ...>
<city>Cutler</city>
...
</property>
<property ...>
<city>Oseola</city>
...
</property>
</listings>
In my textbook (XML 2nd Edition by Patrick Carey) it provides an example of using 'Muenchian Grouping' to find unique selections. The part I don't understand is thus:
It gets to here, in the progression of the example where it states: "
property[generate-id()=generate-id(key("cityNames", "Cutler")[1])]
" which says that this will find the first 'Cutler' in the selection, due to the index of '[1]'. Which given the XML above will return "Cutler"
Now the example progresses to thus: "
property[generate-id()=generate-id(key("cityNames", city)[1])]
" which says that this will find the first and only the first (therefore unique) of each city within the key. Creating a group of unique values of all the city's within. Which given the XML above will return "Argyle Broxton Cutler Fenmore Padua Stratmore Oseola" (note that there is no multiples).
Now, my question is thus: why does the second statement return a range of values, instead of just one?
Thanks
When you define your key, the match expression can match multiple nodes. That node-set is returned when accessing the key by name.
Adding the predicate filter for the first one ensures that you will only get at most one(the first) node returned from the key.
Ok, I suppose the answer I was looking for is thus:
property[generate-id()=generate-id(key("cityNames", city)[1])]
This code finds the first of each city
property[generate-id()=generate-id(key("cityNames", city[1]))]
and this code finds the first of all city's
easy enough, just couldn't see it before.