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 <anj...@wso2.com> 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 <giman...@wso2.com> > 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 <hars...@wso2.com> >> 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: hars...@wso2.com >>> 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 <giman...@wso2.com> >>> 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 <sinth...@wso2.com >>>> > 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 <giman...@wso2.com> >>>>> wrote: >>>>> >>>>>> Hi Sinduja, >>>>>> >>>>>> Thank you for the feedback. >>>>>> >>>>>> On Mon, Jan 19, 2015 at 12:04 PM, Sinthuja Ragendran < >>>>>> sinth...@wso2.com> wrote: >>>>>> >>>>>>> Hi gimantha, >>>>>>> >>>>>>> Please see the comments inline. >>>>>>> >>>>>>> On Sun, Jan 18, 2015 at 11:24 PM, Gimantha Bandara < >>>>>>> giman...@wso2.com> 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 >>>>>>>> Architecture@wso2.org >>>>>>>> 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 >>>>>>> Architecture@wso2.org >>>>>>> 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 >> Architecture@wso2.org >> 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 > Architecture@wso2.org > https://mail.wso2.org/cgi-bin/mailman/listinfo/architecture > > -- Gimantha Bandara Software Engineer WSO2. Inc : http://wso2.com Mobile : +94714961919
_______________________________________________ Architecture mailing list Architecture@wso2.org https://mail.wso2.org/cgi-bin/mailman/listinfo/architecture