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

Reply via email to