Need to create WSO2 DSS service which can read parameter from url - wso2

I have created a simple dss service which by inputing cust_id it gives me the customer data.
I have exposed this webservice as http get resource with the following url
GET /services/getCustDetailDSS/getDetail?cid=101
Corrsponding xml code for my service is as follows
<data name="getCustomerDetailDSS" serviceGroup="" serviceNamespace="">
<description/>
<config id="mydb">
<property name="carbon_datasource_name">mydb</property>
</config>
<query id="get_customer_detail" useConfig="mydb">
<sql>select identifier,user_status from customer_detail where identifier = :cid</sql>
<param name="cid" paramType="SCALAR" sqlType="STRING"/>
<result element="customer">
<element column="identifier" name="cid" xsdType="xs:string"/>
<element column="user_status" name="status" xsdType="xs:string"/>
</result>
</query>
<operation name="get_customer_detail_operation">
<call-query href="get_customer_detail">
<with-param name="cid" query-param="identifier"/>
</call-query>
</operation>
<resource method="GET" path="/getDetail">
<call-query href="get_customer_detail">
<with-param name="cid" query-param="cid"/>
</call-query>
</resource>
</data>
But now i want the dss service to read cust_id from url instead of passing it as a parameter.
i.e i want to hit dss service as
GET /services/getCustDetailDSS/cid/101/getDetail
How can i do this in DSS ?
Can anyone provide wat changes i need to do in my dss?

For GET /services/getCustDetailDSS/getDetail/cid/101
You have to edit your resource path as follows.
<resource method="GET" path="getDetail/cid/{cid}">

With WSO2 DSS 3.2.1, you can now define your query string parameter as below:
<param name="cid" sqlType="QUERY_STRING"/>
instead of:
<param name="cid" paramType="SCALAR" sqlType="STRING"/>
and your URL should look like:
.../getDetail?cid=101

Related

WSO2 MI Validators and Array query parameters for a Data Service

I don't know how to create a validator for 2 variables:
Q1. An user code that needs to be checked if exists prior to running the SQL query. I have an endpoint to check if the user code exists or not, how do I make it into a validator?
Q2. An array of dates, the best I could do was to use a pattern validator. I know there's also the possibility to set a parameter with paramType="array" and sqlType="date", but how can I configure this in the query parameters of the resource?
Please check the Data Service definition below:
<data name="APIDataService" serviceNamespace="" serviceGroup="" transports="http https local">
<description />
<config id="postgresDataService">
<property name="carbon_datasource_name">APIPostgres</property>
</config>
<!-- TODO: Q1. Here is the resource I want to use to validate the user code -->
<query id="validateUserCode" useConfig="postgresDataService">
<sql>
SELECT ( EXISTS ( SELECT 1
FROM user
WHERE code ILIKE :user_code ) )::INT AS does_user_exist
</sql>
<param name="user_code" sqlType="string" />
<result element="result">
<element column="does_user_exist" name="doesUserExist" xsdType="integer" />
</result>
</query>
<resource method="GET" path="validateUserCode">
<call-query href="validateUserCode">
<with-param name="user_code" query-param="user_code" />
</call-query>
</resource>
<query id="apiReportUserTotalEventsByDay" useConfig="postgresDataService">
<sql>
SELECT
calendar_date,
record_date,
user_code,
event_type_id,
event_count
FROM user_event
WHERE 1=1
AND calendar_date BETWEEN :calendar_date_start AND :calendar_date_end
AND record_date = ANY( ('{'||:record_date_array||'}')::DATE[] )
AND user_code = :user_code
</sql>
<!-- TODO: Q1. Here is the user code I want to validate -->
<param name="user_code" paramType="scalar" sqlType="string" />
<param name="calendar_date_start" paramType="scalar" sqlType="date" />
<param name="calendar_date_end" paramType="scalar" sqlType="date" />
<!-- TODO: Q2. Here is the array of date that I want to know
how I could convert into an paramType="array" sqlType="date" -->
<param name="record_date_array" paramType="scalar" sqlType="string" >
<validatePattern pattern="\s*\d{4}-\d{2}-\d{2}\s*(,\s*\d{4}-\d{2}-\d{2}\s*)*" />
</param>
<result element="result">
<element column="calendar_date" name="calendar_date" xsdType="string" />
<element column="record_date" name="record_date" xsdType="string" />
<element column="user_code" name="user_code" xsdType="string" />
<element column="event_type_id" name="event_type_id" xsdType="integer" />
<element column="event_count" name="event_count" xsdType="integer" />
</result>
</query>
<resource method="GET" path="apiReportUserTotalEventsByDay">
<call-query href="apiReportUserTotalEventsByDay">
<with-param name="user_code" query-param="user_code" />
<with-param name="calendar_date_start" query-param="calendar_date_start" />
<with-param name="calendar_date_end" query-param="calendar_date_end" />
<with-param name="record_date_array" query-param="record_date_array" />
</call-query>
</resource>
</data>

Is there any native functionality available in wso2 esb for fetching the data from multiple excel file sheets?

i want to extract the data from multiple sheets of excel files using wso2 esb or wso2 dss functionality. Just i want to do those task with native components of wso2 only not with custom class mediator.
Is it possible means please someone guide me with some samples or steps?
Using the DSS you can add an excel file as datasource, and then specify a query where you tell it the worksheet and columns to retrieve as follows. There is a json and xml sample 'query' both exposed as a resource. You can add configs for more excel sheets or create separate DataServices.
<data name="excel-ds" transports="http https">
<config id="SAMPLE">
<property name="excel_datasource">/file/path/sample.xlsx</property>
</config>
<query id="GET_JSON" useConfig="SAMPLE">
<excel>
<workbookname>sampledata</workbookname>
<hasheader>true</hasheader>
<startingrow>2</startingrow>
<maxrowcount>-1</maxrowcount>
</excel>
<result outputType="json">{
"Rows": {
"Row": [
{
"EMPnr": "$EMPnr",
"Name": "$name",
"Email": "$email"
}
]
}
}</result>
</query>
<query id="GET_XML" useConfig="SAMPLE">
<excel>
<workbookname>samplesheet</workbookname>
<hasheader>true</hasheader>
<startingrow>2</startingrow>
<maxrowcount>-1</maxrowcount>
</excel>
<result element="Rows" rowName="Row">
<element column="empnr" name="Empnr" xsdType="string"/>
<element column="name" name="Name" xsdType="string"/>
<element column="email" name="Email" xsdType="string"/>
</result>
</query>
<resource method="GET" path="samplejson">
<call-query href="GET_JSON"/>
</resource>
<resource method="GET" path="samplexml">
<call-query href="GET_XML"/>
</resource>
</data>
For documentation check wso2.com

how to insert all records of excel sheet into sql data base using wso2 dss 6.4.0?

I am new to wso2 6.4.0. I have to insert excel data to sql so i choose wso2 dss. Using dss records fetching correctly and inserting too but inserting only one record(top one only) remain records getting skipped. I used nested query option also to retrieve as well as insertion.
<query id="readExcelData" useConfig="excelConfig">
<excel>
<workbookname>sheet1</workbookname>
<hasheader>true</hasheader>
<startingrow>2</startingrow>
<maxrowcount>-1</maxrowcount>
<headerrow>1</headerrow>
</excel>
<result element="Products" rowName="Product">
<element column="ID" name="ID" xsdType="xs:string"/>
<element column="Model" name="Model" xsdType="xs:string"/>
<element column="Classification" name="Classification" xsdType="xs:string"/>
<call-query href="insertIntoSql" requiredRoles="">
<with-param name="ID" query-param="ID" />
<with-param name="Model" query-param="Model" />
<with-param name="Classification" query-param="Classification" />
</call-query>
</result>
</query>
<operation name="excelFileProcessing" returnRequestStatus="true">
<call-query href="readExcelData"/>
</operation>
<query id="insertIntoSql" useConfig="sqlConfig">
<sql>insert into dbo.myProductList(ID,Model,Classification) values(:ID,:Model,:Classification)</sql>
<param name="ID" sqlType="STRING" />
<param name="Model" sqlType="STRING" />
<param name="Classification" sqlType="STRING" />
</query>
Once you retrieve records from Excel sheet you are getting sets of records. Therefore you have to write a synapse config to insert each record. For that, you have iterate over the payload of excel sheet's data (for each record) and insert. You can use iterate mediator. For an example you can implement something similar to this.
You can follow,
In the proxy service/ API call the dataservice to get excel sheet's
data.
Iterate over the result set.
In each iteration, create the
payload to insert data to DB and call the dataservice to invoke the
insert data query.
Invoke the proxy service / API.

Create Data Service with inner join

I'm trying to create a service with an inner join query but it returns this error:
org.postgresql.util.PSQLException: A result was returned when none was expected.
This is my service:
<data name="consultarPersona" transports="http https local">
<config enableOData="true" id="mi_datasource">
<property name="carbon_datasource_name">fuente_datos</property>
</config>
<query id="contactos_registrados" useConfig="mi_datasource">
<sql>select * from t_contacto inner join t_datos_contacto on t_contacto.id = t_datos_contacto.id</sql>
</query>
<operation name="obtenerDatosContactos">
<call-query href="contactos_registrados"/>
</operation>
</data>
You should specify which columns do you want to return and generate the response, the result is an service like this:
<data name="consultarPersona" transports="http https local">
<config enableOData="true" id="mi_datasource">
<property name="carbon_datasource_name">fuente_datos</property>
</config>
<query id="contactos_registrados" useConfig="mi_datasource">
<sql>select name, age from t_contacto inner join t_datos_contacto on t_contacto.id = t_datos_contacto.id</sql>
<result element="contactoCollection" rowName="contacto">
<element column="name" name="name" xsdType="xs:string"/>
<element column="age" name="age" xsdType="xs:string"/>
</result>
</query>
<operation name="obtenerDatosContactos">
<call-query href="contactos_registrados"/>
</operation>
</data>
I hope this coudl help you.

How to set client request parameter as a offset in wso2esb

i'm using wso2esb4.7.0 and wso2dss 3.1.0.My proxy service in esb allows to retrieve the perticular no of records from database.For that i have to use limit and offset in the query which is written in wso2dss.The query is as follows :
<sql>SELECT firstname, lastname FROM public.testlogin limit 5 offset ?</sql>
As per above query i have set the limit in query but offset is provded by client in request.My requirement is i have to retrieve the 5 records from offset of client requestNoq question is..How should i retrieve the offset which is in the client request.client request is as follows :
LogMediator To: /services/GetTaskDetails, MessageID: urn:uuid:caeaaebb-2239-4639-b1a2-094c22650de0, Direction: request, StartRecord = 6 Envelope: . . . .
here StartRecord is the offset in above request and i wanted to set it as offset in wso2 dss query please suggest something..
The query should work with the query and operation defined as follows:
`
<query id="SELECT" useConfig="MyDataSource">
<sql> SELECT firstname, lastname FROM public.testlogin limit 5 offset ? ;</sql>
<result element="patients" rowName="patient">
<element column="firstname" name="firstname" xsdType="string"/>
<element column="lastname" name="lastname" xsdType="string"/>
</result>
<param name="offset" optional="false" sqlType="INTEGER"/>
</query>
<operation name="getPatients">
<call-query href="SELECT">
<with-param name="offset" query-param="offset"/>
</call-query>
</operation>
`
You can modify the 'query' section in your dbs to set a input param. See the below example. It has a param name as employeeNumber. Which means, data services server will pickup the employeeNumber parameter from the SOAP request. You can modify appropriately. If there are more than one variable (ie. '?' symbols), then the ordering of the param is important.
The complete dbs sample can be found here in RDBMSSample.dbs.
<query id="employeesByNumberSQL" useConfig="default">
<sql>select * from Employees where employeeNumber = ?</sql>
<result element="employees" rowName="employee">
<element column="lastName" name="last-name" xsdType="string"/>
<element column="firstName" name="first-name" xsdType="string"/>
<element column="email" name="email" xsdType="string"/>
<element column="salary" name="salary" xsdType="double"/>
</result>
<param name="employeeNumber" ordinal="1" paramType="SCALAR" sqlType="INTEGER" type="IN"/>
</query>