@Roshan, These APIs are tightly coupled with the product. If user wants to migrate to a newer version, then the user has to use the newer APIs that come with the new product version. We have started the separate mail thread to discuss this.
@Harshan Again *GET /analytics/tables/is-exists?tableName=<table-name> *will conflict with API #5, since each path parameter is optional. So I changed the API #3 like this,, *GET /analytics/table_exists?tableName=<table-name>* On Fri, Feb 13, 2015 at 11:41 AM, Harshan Liyanage <[email protected]> wrote: > Hi Gimantha, > > I think it's better if you could change the API #3 to something more > meaningful like *GET /analytics/tables/is-exists?tableName=<table-name>*. > When you have the following format for that API, it's more like you are > trying to fetch the table instead of checking for its existence. Anyway > that's a minor issue and may be not-applicable to your domain. > > 3. Check if a table exists > *GET /analytics/tables?tableName=<table-name>* > ; table-name - The name of the table being checked. > > Thanks, > > Lakshitha Harshan > Software Engineer > Mobile: *+94724423048* > Email: [email protected] > Blog : http://harshanliyanage.blogspot.com/ > *WSO2, Inc. :** wso2.com <http://wso2.com/>* > lean.enterprise.middleware. > > On Fri, Feb 13, 2015 at 9:49 AM, Roshan Wijesena <[email protected]> wrote: > >> Hi Gimantha, >> >> Don't we need to maintain a version with an API? >> >> Regards >> Roshan >> >> On Fri, Feb 13, 2015 at 3:08 AM, Gimantha Bandara <[email protected]> >> wrote: >> >>> Hi all, >>> I changed the APIs so they follow the convention and i tested if there >>> are conflicts between some APIs. JAX RS treats *GET >>> /analytics/tables/{tableName}/{from} *, *GET >>> /analytics/tables/{tableName}/recordcount *and *GET >>> /analytics/tables/{tableName}/indices* as different APIs, so there will >>> not be any conflict. >>> >>> Changed APIs : >>> >>> 1. Create a table >>> *POST /analytics/tables* >>> { >>> tableName : "<table-name>" >>> } >>> ; table-name - The name of the table to be created. >>> >>> 2. Delete a table. >>> *DELETE /analytics/tables*/*{tableName}* >>> >>> ; tableName - The name of the table to be deleted. >>> >>> 3. Check if a table exists >>> *GET /analytics/tables?tableName=<table-name>* >>> ; table-name - The name of the table being checked. >>> >>> 4. List All the tables >>> *GET /analytics/tables* >>> ;Response will be an JSON array of table names. e.g. [ "table1" , >>> "table2" , "table3" ] >>> >>> 5. Get the records from a table. >>> *GET /analytics/tables/{tableName}/{from}/{to}/{start}/{count}* >>> ; tableName - The name of the table from which the records are retrieved. >>> ; from - The starting time to get records from. >>> ; to - The ending time to get records to. >>> ; start - The paginated index from value >>> ; count - The paginated records count to be read >>> ; response - takes the format of the request content of No.7 >>> >>> 7. Create records ( can be created in different tables or in the same ) >>> *POST /analytics/records* >>> ; Content - A list of records in json format like in below. >>> [ >>> { >>> "id": "id1", (optional), >>> "tableName": "tableName1", >>> "timestamp": "<long-value>", (optional) >>> "values": >>> { >>> "columnName1": "value1", >>> "columnName2": "value2" >>> } >>> }, >>> { >>> "tableName": "tableName2", >>> "values": >>> { >>> "columnName1": "value1", >>> "columnName2": "value2" >>> } >>> }, >>> ] >>> >>> 8. Delete records >>> *DELETE /analytics/tables/{tableName}/{timeFrom}/{timeTo}* >>> ; tableName - Name of the table from which the records are deleted. >>> ; timeFrom - The starting time to delete records from. >>> ; timeTo - The end time to delete records to. >>> >>> 9. Update a set of records >>> *PUT /analytics/records* ( PATCH will be more suitable, but jax rs does >>> not give PATCH method out of the box so we have to implement it) >>> ; Content - As same as the POST method for creating records >>> >>> 10. Get the record count of table >>> *GET /analytics/tables/{tableName}/recordcount* >>> ; tableName - The name of the table >>> >>> 11. Create Indices for a table >>> *POST /analytics/tables/{tableName}/indices* >>> ; tableName - The name of the table of which the indices are set >>> ; Content - takes the following format. TYPE is one of "INTEGER", >>> "BOOLEAN", "DOUBLE", "STRING", "FLOAT", "LONG" >>> { >>> "indexColumnName1" : "TYPE1", >>> "indexColumnName2" : "TYPE2" >>> } >>> >>> 12. get the indices of a table >>> *GET /analytics/tables/{tableName}/indices* >>> ; tableName - The name of the table >>> ; Response will be of the format of the previous POST request's Content. >>> >>> 13. Clear the indices of a table >>> *DELETE /analytics/tables/{tableName}/indices* >>> ; tableName - The name of the table >>> >>> 14. Search records of a table >>> *POST /analytics/search* >>> ; Content - takes the following format >>> { >>> "tableName": "sampleTableName", >>> "language": "sampleLanguageName", >>> "query": "sampleQuery", >>> "start": "start-location-of-the-result", >>> "count": "maximum-number-of-entries-to-return" >>> } >>> >>> On Wed, Jan 21, 2015 at 8:38 AM, Anjana Fernando <[email protected]> >>> wrote: >>> >>>> Hi Gimantha, >>>> >>>> You haven't really replied to Sinthuja's points there. We have to >>>> decide if we are going ahead with Sinthuja's suggestions, or not. Lets >>>> first educate ourselves on the best practices of RESTful API design a bit, >>>> Googling helps [1]. For example, I'm also not sure if should be >>>> /analytics/{tableName}/records or /analytics/records/{tableName}, each has >>>> benefits, like, first approach can have ambiguity issues, specially when >>>> there other operations with optional fields. And also, I guess we will need >>>> to have /analytics/tables/{tableName} for creating tables etc.. or else, >>>> for example when we do a POST for like "/analytics/T1", it may not be that >>>> informative what we are actually doing there. >>>> >>>> [1] >>>> https://www.google.com/search?q=REST+service+design&gws_rd=ssl#q=REST+api+design >>>> >>>> Cheers, >>>> Anjana. >>>> >>>> On Wed, Jan 21, 2015 at 3:35 AM, Gimantha Bandara <[email protected]> >>>> wrote: >>>> >>>>> Hi, >>>>> Goood point!. Initially the search was implemented such a way that it >>>>> returns a list of ids of records that match the query. Now the search >>>>> method is changed, so it returns the records. So +1 for removing the API >>>>> #6. >>>>> >>>>> @Sinduja, @Harshan >>>>> Thanks for the reference links and for the feedback. >>>>> >>>>> On Tue, Jan 20, 2015 at 6:52 PM, Harshan Liyanage <[email protected]> >>>>> wrote: >>>>> >>>>>> Hi Gimantha, >>>>>> >>>>>> Could you please explain the use-case for the API #6? IMO there >>>>>> should not be any operation to fetch a list of records by ids. Instead >>>>>> there could be an API which sends a list of records as the response for a >>>>>> query. >>>>>> >>>>>> For the API #14 you can still use GET method with query strings. I >>>>>> think you have included start & count parameters to control the >>>>>> pagination. >>>>>> For that you can use the HTTP range-header [1] or link headers as >>>>>> mentioned >>>>>> in [2]. >>>>>> >>>>>> [1]. http://otac0n.com/blog/2012/11/21/range-header-i-choose-you.html >>>>>> [2]. https://developer.github.com/v3/#pagination >>>>>> >>>>>> Regards, >>>>>> >>>>>> Lakshitha Harshan >>>>>> Software Engineer >>>>>> Mobile: *+94724423048* >>>>>> Email: [email protected] >>>>>> Blog : http://harshanliyanage.blogspot.com/ >>>>>> *WSO2, Inc. :** wso2.com <http://wso2.com/>* >>>>>> lean.enterprise.middleware. >>>>>> >>>>>> On Tue, Jan 20, 2015 at 6:34 PM, Gimantha Bandara <[email protected]> >>>>>> wrote: >>>>>> >>>>>>> Hi Harshan, >>>>>>> >>>>>>> Thanks for the feedback. The list of IDs of the records to be >>>>>>> retrieved can be too long. So setting a list of ids as a query param is >>>>>>> not >>>>>>> convenient. Even for the Search, we have to pass a query, which can be >>>>>>> too >>>>>>> long. Thats why the post method is used for Search. >>>>>>> >>>>>>> Thanks, >>>>>>> >>>>>>> On Tue, Jan 20, 2015 at 12:52 PM, Sinthuja Ragendran < >>>>>>> [email protected]> wrote: >>>>>>> >>>>>>>> Hi Gimantha, >>>>>>>> >>>>>>>> I think following the conventions will be more intuitive to the >>>>>>>> users, and we should have a proper reason to not follow. And the post >>>>>>>> request is generally needs to be sent to create the object and the >>>>>>>> back end >>>>>>>> is going to decide where to create the tables resource, therefore it >>>>>>>> should >>>>>>>> be POST to '/analytics/tables' and message body should be having the >>>>>>>> table >>>>>>>> name. If you want to use /analytics/{tableName}, then you should >>>>>>>> use PUT rather POST [1]. But IMO POST is the most suitable operation >>>>>>>> for >>>>>>>> this context. >>>>>>>> >>>>>>>> And through out the below given URL patterns, in order to fetch the >>>>>>>> records from a table, you have used '/analytics/records/{tableName}' >>>>>>>> url >>>>>>>> pattern where 'records' is in the middle and it is not the correct data >>>>>>>> hierarchy and again I feel it's not the convention. Basically tables >>>>>>>> contains records and not records contains tables. Therefore if we use >>>>>>>> POST to '/analytics/tables' for create table, then you can use >>>>>>>> simply user 'analytics/{tableName}' to GET/POST for the tables, IMHO >>>>>>>> the >>>>>>>> records is just an additional segment which is not needed to be here. >>>>>>>> >>>>>>>> [1] http://restcookbook.com/HTTP%20Methods/put-vs-post >>>>>>>> >>>>>>>> Thanks, >>>>>>>> Sinthuja. >>>>>>>> >>>>>>>> On Tue, Jan 20, 2015 at 1:29 AM, Gimantha Bandara < >>>>>>>> [email protected]> wrote: >>>>>>>> >>>>>>>>> Hi Sinduja, >>>>>>>>> >>>>>>>>> Thank you for the feedback. >>>>>>>>> >>>>>>>>> On Mon, Jan 19, 2015 at 12:04 PM, Sinthuja Ragendran < >>>>>>>>> [email protected]> wrote: >>>>>>>>> >>>>>>>>>> Hi gimantha, >>>>>>>>>> >>>>>>>>>> Please see the comments inline. >>>>>>>>>> >>>>>>>>>> On Sun, Jan 18, 2015 at 11:24 PM, Gimantha Bandara < >>>>>>>>>> [email protected]> wrote: >>>>>>>>>> >>>>>>>>>>> Hi, >>>>>>>>>>> Currently, I am working on $subject. Basically the methods in >>>>>>>>>>> AnalyticsDataService will be exposed through REST APIs. Please >>>>>>>>>>> refer to >>>>>>>>>>> Architecture mail thread "*[Architecture] BAM 3.0 Data Layer >>>>>>>>>>> Implementation / RDBMS / Distributed Indexing / Search*" for >>>>>>>>>>> more Details. Following are the supported REST APIs. >>>>>>>>>>> >>>>>>>>>>> 1. Create a table >>>>>>>>>>> *POST /analytics/{tableName}* >>>>>>>>>>> ; tableName - The name of the table to be created. >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> IMHO the above should be POST to '/analytics/*tables*' and the >>>>>>>>>> request content should have the table name as given below. >>>>>>>>>> { >>>>>>>>>> "tableName" : "Test" >>>>>>>>>> } >>>>>>>>>> >>>>>>>>> Since the POST takes only the table name, it is straightforward to >>>>>>>>> use it as a path parameter. >>>>>>>>> >>>>>>>>>> >>>>>>>>>>> 2. Delete a table >>>>>>>>>>> *DELETE /analytics/{tableName} * >>>>>>>>>>> ; tableName - The name of the table to be deleted. >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>>> 3. Check if a table exists >>>>>>>>>>> *GET /analytics/{tableName} * >>>>>>>>>>> ; tableName - The name of the table being checked. >>>>>>>>>>> >>>>>>>>>>> 4. List All the tables >>>>>>>>>>> *GET /analytics/tables* >>>>>>>>>>> ;Response will be an JSON array of table names. e.g. [ "table1" >>>>>>>>>>> , "table2" , "table3" ] >>>>>>>>>>> >>>>>>>>>>> 5. Get the records from a table. >>>>>>>>>>> *GET /analytics/records/{tableName}/{from}/{to}/{start}/{count} * >>>>>>>>>>> ; tableName - The name of the table from which the records are >>>>>>>>>>> retrieved. >>>>>>>>>>> ; from - The starting time to get records from. >>>>>>>>>>> ; to - The ending time to get records to. >>>>>>>>>>> ; start - The paginated index from value >>>>>>>>>>> ; count - The paginated records count to be read >>>>>>>>>>> ; response - takes the format of the request content of No.7 >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Do we need to have 'records' in the URL? I think it's better to >>>>>>>>>> have */analytics/{tableName}/{from}/{to}/{start}/{count} * >>>>>>>>>> >>>>>>>>> >>>>>>>>> "records" is there to avoid conflicts with other contexts. As an >>>>>>>>> example, If we remove "records", the URL will take the format >>>>>>>>> "/analytics/{tableName}", which is already a defined REST API. >>>>>>>>> >>>>>>>>>> >>>>>>>>>>> 6. Get the records from a table (By IDs) >>>>>>>>>>> *POST /analytics/records/{tableName}* >>>>>>>>>>> ; tableName - The name of the table from which the records are >>>>>>>>>>> retrieved. >>>>>>>>>>> ; Content - A List of IDs of the records to be retrieved in the >>>>>>>>>>> following format. >>>>>>>>>>> [ "id1" , "id2" , "id3" ] >>>>>>>>>>> ; response - takes the format of the request content of No.7 >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Similarly can we have this as * /analytics/{tableName}?* >>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> 7. Create records ( can be created in different tables or in the >>>>>>>>>>> same ) >>>>>>>>>>> *POST /analytics/records* >>>>>>>>>>> ; Content - A list of records in json format like in below. >>>>>>>>>>> [ >>>>>>>>>>> { >>>>>>>>>>> "id": "id1", >>>>>>>>>>> "tenantId": -1234, >>>>>>>>>>> "tableName": "tableName1", >>>>>>>>>>> "timestamp": "yyyy-mm-dd hh:mm:ss", >>>>>>>>>>> "values": >>>>>>>>>>> { >>>>>>>>>>> "columnName1": "value1", >>>>>>>>>>> "columnName2": "value2" >>>>>>>>>>> } >>>>>>>>>>> }, >>>>>>>>>>> { >>>>>>>>>>> "id": "id2", >>>>>>>>>>> "tenantId": -1234, >>>>>>>>>>> "tableName": "tableName2", >>>>>>>>>>> "timestamp": "yyyy-mm-dd hh:mm:ss", >>>>>>>>>>> "values": >>>>>>>>>>> { >>>>>>>>>>> "columnName1": "value1", >>>>>>>>>>> "columnName2": "value2" >>>>>>>>>>> } >>>>>>>>>>> }, >>>>>>>>>>> ] >>>>>>>>>>> >>>>>>>>>>> 8. Delete records >>>>>>>>>>> *DELETE /analytics/records/{tableName}/{timeFrom}/{timeTo}* >>>>>>>>>>> ; tableName - Name of the table from which the records are >>>>>>>>>>> deleted. >>>>>>>>>>> ; timeFrom - The starting time to delete records from. >>>>>>>>>>> ; timeTo - The end time to delete records to. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>> Again do we need to have 'records' in the middle? IMHO >>>>>>>>>> /analytics/{tableName}/{timeFrom}/{timeTo} is better. >>>>>>>>>> >>>>>>>>>> 9. Update records >>>>>>>>>>> *PUT /analytics/records* >>>>>>>>>>> ; Content - As same as the POST method for creating records >>>>>>>>>>> >>>>>>>>>>> 10. Get the record count of table >>>>>>>>>>> *GET /analytics/count/{tableName}* >>>>>>>>>>> ; tableName - The name of the table >>>>>>>>>>> >>>>>>>>>>> 11. Create Indices for a table >>>>>>>>>>> *POST /analytics/indices/{tableName}* >>>>>>>>>>> ; tableName - The name of the table of which the indices are set >>>>>>>>>>> ; Content - takes the following format. TYPE is one of >>>>>>>>>>> "INTEGER", "BOOLEAN", "DOUBLE", "STRING", "FLOAT", "LONG" >>>>>>>>>>> { >>>>>>>>>>> "indexColumnName1" : "TYPE1", >>>>>>>>>>> "indexColumnName2" : "TYPE2" >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>>> 12. get the indices of a table >>>>>>>>>>> *GET /analytics/indices/{tableName}* >>>>>>>>>>> ; tableName - The name of the table >>>>>>>>>>> ; Response will be of the format of the previous POST request's >>>>>>>>>>> Content. >>>>>>>>>>> >>>>>>>>>>> 13. Clear the indices of a table >>>>>>>>>>> *DELETE /analytics/indices/{tableName}* >>>>>>>>>>> ; tableName - The name of the table >>>>>>>>>>> >>>>>>>>>>> 14. Search records of a table >>>>>>>>>>> *POST /analytics/search* >>>>>>>>>>> ; Content - takes the following format >>>>>>>>>>> { >>>>>>>>>>> "tableName": "sampleTableName", >>>>>>>>>>> "language": "sampleLanguageName", >>>>>>>>>>> "query": "sampleQuery", >>>>>>>>>>> "start": "start-location-of-the-result", >>>>>>>>>>> "count": "maximum-number-of-entries-to-return" >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> IMHO this should be a GET request. >>>>>>>>>> >>>>>>>>> >>>>>>>>> Here the problem is, that the search method in >>>>>>>>> AnalyticsDataService takes few parameters. If we are to implement it >>>>>>>>> as a >>>>>>>>> GET, then we will have to put all the parameters in the URL itself. >>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> Sinthuja. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>>> If a method does not have a specific response mentioned above, >>>>>>>>>>> the response will take the following format. >>>>>>>>>>> >>>>>>>>>>> { >>>>>>>>>>> "status" : "statusValue", >>>>>>>>>>> "message" : "sampleMessage" >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> Suggestions and feedbacks are appreciated. >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> >>>>>>>>>>> -- >>>>>>>>>>> Gimanthaa Bandara >>>>>>>>>>> Software Engineer >>>>>>>>>>> WSO2. Inc : http://wso2.com >>>>>>>>>>> Mobile : +94714961919 >>>>>>>>>>> >>>>>>>>>>> _______________________________________________ >>>>>>>>>>> Architecture mailing list >>>>>>>>>>> [email protected] >>>>>>>>>>> https://mail.wso2.org/cgi-bin/mailman/listinfo/architecture >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> -- >>>>>>>>>> *Sinthuja Rajendran* >>>>>>>>>> Senior Software Engineer <http://wso2.com/> >>>>>>>>>> WSO2, Inc.:http://wso2.com >>>>>>>>>> >>>>>>>>>> Blog: http://sinthu-rajan.blogspot.com/ >>>>>>>>>> Mobile: +94774273955 >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> _______________________________________________ >>>>>>>>>> Architecture mailing list >>>>>>>>>> [email protected] >>>>>>>>>> https://mail.wso2.org/cgi-bin/mailman/listinfo/architecture >>>>>>>>>> >>>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> -- >>>>>>>>> Gimantha Bandara >>>>>>>>> Software Engineer >>>>>>>>> WSO2. Inc : http://wso2.com >>>>>>>>> Mobile : +94714961919 >>>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> -- >>>>>>>> *Sinthuja Rajendran* >>>>>>>> Senior Software Engineer <http://wso2.com/> >>>>>>>> WSO2, Inc.:http://wso2.com >>>>>>>> >>>>>>>> Blog: http://sinthu-rajan.blogspot.com/ >>>>>>>> Mobile: +94774273955 >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>> >>>>>>> >>>>>>> -- >>>>>>> Gimantha Bandara >>>>>>> Software Engineer >>>>>>> WSO2. Inc : http://wso2.com >>>>>>> Mobile : +94714961919 >>>>>>> >>>>>> >>>>>> >>>>> >>>>> >>>>> -- >>>>> Gimantha Bandara >>>>> Software Engineer >>>>> WSO2. Inc : http://wso2.com >>>>> Mobile : +94714961919 >>>>> >>>>> _______________________________________________ >>>>> Architecture mailing list >>>>> [email protected] >>>>> https://mail.wso2.org/cgi-bin/mailman/listinfo/architecture >>>>> >>>>> >>>> >>>> >>>> -- >>>> *Anjana Fernando* >>>> Senior Technical Lead >>>> WSO2 Inc. | http://wso2.com >>>> lean . enterprise . middleware >>>> >>>> _______________________________________________ >>>> Architecture mailing list >>>> [email protected] >>>> https://mail.wso2.org/cgi-bin/mailman/listinfo/architecture >>>> >>>> >>> >>> >>> -- >>> Gimantha Bandara >>> Software Engineer >>> WSO2. Inc : http://wso2.com >>> Mobile : +94714961919 >>> >>> _______________________________________________ >>> Architecture mailing list >>> [email protected] >>> https://mail.wso2.org/cgi-bin/mailman/listinfo/architecture >>> >>> >> >> >> -- >> Roshan Wijesena. >> Senior Software Engineer-WSO2 Inc. >> Mobile: *+94719154640 <%2B94719154640>* >> Email: [email protected] >> *WSO2, Inc. :** wso2.com <http://wso2.com/>* >> lean.enterprise.middleware. >> >> _______________________________________________ >> Architecture mailing list >> [email protected] >> https://mail.wso2.org/cgi-bin/mailman/listinfo/architecture >> >> > > _______________________________________________ > Architecture mailing list > [email protected] > https://mail.wso2.org/cgi-bin/mailman/listinfo/architecture > > -- Gimantha Bandara Software Engineer WSO2. Inc : http://wso2.com Mobile : +94714961919
_______________________________________________ Architecture mailing list [email protected] https://mail.wso2.org/cgi-bin/mailman/listinfo/architecture
