Use of Webhandler - how to

Posted by goo on 13-Sep-2019 13:13

11.7/12.0

I am about to start a project where we are going to implement some REST services. We are planning a structure like this:

/api/v1/customers/{OrganizationId}/getCustomerBySSN/{ssn}                                  GET

/api/v1/customers/{OrganizationId}/getCustomerByCustomerId/{CustomerId}          GET

/api/v1/customers/{OrganizationId}/updateCustomerBySSN/{ssn}                             POST

/api/v1/customers/{OrganizationId}/deleteCustomerBySSN/{ssn}                              DELETE

/api/v1/products/{OrganizationId}                                                                               GET

/api/v1/{OrganizationId}/getProductsByCustomerId/{customers}                               GET

and so on.... first of all, do I need to make a handler for each REST structure (like the above)?

I am not going to use the business structure of progress. I am kind of thinking of having the webhandler as a transporter. All business logic will be in another layer, as we may call it direct or using Appserver calls. 

I was thinking implementing something like this:

/api/{Version}/{MethodType}/{OrganizationId}/{Method}/....

Any thoughts? 

Geir Otto

All Replies

Posted by egarcia on 13-Sep-2019 13:52

Hello Geir Otto,

When you work with a RESTful approach, the URIs represent resources and the entity names would a noun rather than a verb.

(This is different than the RPC model where your URIs would correspond to an operation/procedure).

I see that you have the need of working with CustomerId and SSN.

Your API would look like the following:

/api/v1/organization/{OrganizationId}/customer/ssn/{ssn}                GET

/api/v1/organization/{OrganizationId}/customer/{CustomerId}          GET

/api/v1/organization/{OrganizationId}/customer/ssn/{ssn}                POST

/api/v1/organization/{OrganizationId}/customer/ssn/{ssn}                DELETE

/api/v1/products/organization/{OrganizationId}                                 GET

/api/v1/organization/{OrganizationId}/product/{CustomerId}             GET

Take a look at the RESTful APIs commonly used on the internet.

I hope this helps,

Edsel

Posted by egarcia on 13-Sep-2019 13:52

Hello Geir Otto,

When you work with a RESTful approach, the URIs represent resources and the entity names would a noun rather than a verb.

(This is different than the RPC model where your URIs would correspond to an operation/procedure).

I see that you have the need of working with CustomerId and SSN.

Your API would look like the following:

/api/v1/organization/{OrganizationId}/customer/ssn/{ssn}                GET

/api/v1/organization/{OrganizationId}/customer/{CustomerId}          GET

/api/v1/organization/{OrganizationId}/customer/ssn/{ssn}                POST

/api/v1/organization/{OrganizationId}/customer/ssn/{ssn}                DELETE

/api/v1/products/organization/{OrganizationId}                                 GET

/api/v1/organization/{OrganizationId}/product/{CustomerId}             GET

Take a look at the RESTful APIs commonly used on the internet.

I hope this helps,

Edsel

Posted by sjellin.dovetail on 13-Sep-2019 14:02

Hi Geir,

 I stand to correction but from what I recall / struggled with is when using the REST Adapter - anything you don't explicitly map is lost between tomcat and the appserver. I believe in PASOE there is a real webhandler where you can do more generic mapping to a single handler or via a simple file map urls to specific handlers and still be able have access to the raw request. I really want to get to PASOE just for the simpler REST mapping and access to more of the request.

 One comment on your structure - the HTTP Method tells what the consumer what is being done - don't reencode it in the URL.

 as an example of the API I have

../[FRWUat|FRWLive]/rest/FreightWare/V1 - this gives me uat or live rest is forced, FreightWare is the app, V1 is the current ever growing V1 of the API.

 GET ../Waybills{ID} gets a single waybill but also returns a lot of data about the waybill

 GET ../Waybills (gets one or more depending on criteria passed in the body) - minimal data at header level only.

 PUT ../Waybills/{ID} - update a single waybill

 POST ../Waybills - create 1 or more waybill based on JSON struct.

 DELETE - I generally do based on a single ID.

 I use a similar pattern for everything unless the particular function doesn't match the pattern.

 If you like I send you a link to one of the publicly accessible clients API's to have a look if you think it might help.

Posted by sjellin.dovetail on 13-Sep-2019 14:09

As an alternative to different "urls" for the get one could encode it by query parameter like so: /api/v1/organisation/{OrganisationId}/customer?id=1&ssn=2 to allow for complex queries. Nulls can be ignored, non nulls appended into the Query.

Or do something silly like i did and build a filter json object that gets passed in the header / body for gets etc :)

Posted by goo on 13-Sep-2019 14:12

Ok, so I would set it up like this in the OpenEdge.conf file:
 
handler1= MyProjectHandler:/api/v1/organization/{OrganizationId}/customer/ssn/{ssn}
handler2= MyProjectHandler:
/api/v1/organization/{OrganizationId}/customer/{CustomerId}
:
:
HandlerN= MyProjectHandler:/api/v1/organi…….
 
I believe it would be easier to do it like this.
 
//Geir Otto

Posted by Michael Jacobs on 13-Sep-2019 14:13

Building upon Edsel's suggestion, I see the /api service root in the path as not adding a lot of value.  Having a version'd resource access looks like a good idea - but you may have other options than as a static value in the URL path.  If the version was an URL option, your service handler code can easily dispatch to derived ABL classes where each child adds to the previous version's functionality (within a reasonable # of versions).   To use one of Edsel's samples to give you another thought:  

/organization/{OrganizationId}/customer/ssn/{ssn}?vers=1               GET

Posted by goo on 13-Sep-2019 15:28

Using ?vers=n  will give me more complexity reading the query, so that I would not like.
 
//Geir Otto
 

Posted by Peter Judge on 23-Sep-2019 18:50

We have a webhandler in the box that can help, called the Data Object Handler  (DOH for short). Basically you create some JSON files that tell the DOH which URL + method runs which procedure+function/class+method, and what the parameters are.

It was written for Business Entities but it works with just about any ABLcode.

There's slides describing it from a presentation I did at http://pugsa.org/wp-content/uploads/2019/03/PJ_pasoe_doh.pdf  and doc at  https://docs.progress.com/bundle/service-developer-guide/page/Use-a-Data-Object-Handler.html .

One webhandler can be used for many/all request URIs.

Regardless of whether you use the DOH or your own webhandler you will need to add a handlerN line for all of the path parameters (the {id} stuff).

This thread is closed