RESTful api for dynamic showform on top of spring mvc - model-view-controller

I want to build a typical mvc app for CRUD of simple items, the api s should be RESTful. The catch here is, that i have a large pallete of items that needs to be initialized. On the server side those items are defined as java beans and the corresponding create form for the item is dynamically created from the field information(data type, validation constraints etc) harvested from the bean.
I am new to REST and just read up about how the urls should be nouns defining the resource and action specified by HTTP verb. In that perspective how to model something like
.../client/showForm?type=xyz from non RESTful way to RESTful one ?? My intention here is to tell the server to dynamically construct and send back a CREATE form for client of type xyz. The obvious problem with url i mentioned above is that it specifies action in the url which, from what i have read, makes it non RESTful.

When I think of REST, I think of resources. I think of data. In other words, I don't think of REST as being something that I would typically use to retrieve a form, which is a user interface component.
REST is an architectural style that is used to identify a resource on a server using a uniform resource identifier, or URI. Additionally, actions performed on those resources identified by the URI are determined based on the specific HTTP Method used in the request: GET, POST, PUT, DELETE, etc.
Thus, let's say you have a Client object. That client object might have the following properties:
Name
Location
AccountNumber
If I wanted to retrieve the data for a single client, I might use the following URI:
GET /client/xyz/ # xyx is the accountnumber used to identify the client.
I would use a GET method, since REST describes GET as being the method to use when retrieving data from the server.
The data could theoretically be returned in HTML, since REST is not a standard but more like a series of flexible guidelines; however, to really decouple my data from my user interface, I would choose to use something platform independent like JSON or XML to represent the data.
Next, when adding a client to the collection on the server, I would use the /client/ URI pattern, but I would use the HTTP Method POST, which is used when adding a resource to a collection on the server.
# Pass the data as JSON to the server and tell the server to add the client to the
# collection
POST /client/ {"accountnumber":"abc" , "Name" : "Jones" , "Location" : "Florida"}
If I were to modify an existing record on the server or replace it, I would most likely use the HTTP Method PUT, since REST guidelines say that PUT should be used if repeating the same operation repeatedly would not change the state of the server.
# Replace the client abc with a new resource
PUT /client/abc/ {"accountnumber":"abc" , "Name" : "Bob Jones" , "Location" : "Florida"}
The general idea behind REST is that it is used to identify a resource and then take action on that resource based on what HTTP Method is used.
If you insist on coupling your data with your view, one way accomplish this and retrieve the actual form, with the client data, could be to represent the form as a resource itself:
GET /client/abc/htmlform/
This URL would of course return your client data for client abc, but in an HTML form that would be rendered by the browser.
While my style of coding utilizes data transports such as JSON or XML to abstract and separate my data from my view, you could very well transport that data as HTML. However, the advantage of using JSON or XML is that your RESTful API becomes platform independent. If you ever expand your API to where other developers wish to consume it, they can do so, regardless of what specific platform or programming language they are using. In other words, the API could be used my PHP, Java, C#, Python, Ruby, or Perl developers.
In other words, any language or platform that can make HTTP requests and can send GET, POST, PUT, DELETE requests can be used to extend or build upon your API. This is the true advantage of REST.
For more information on setting up your controllers to use REST with Spring MVC, see this question. Additionally, check out the Spring MVC Documentation for more information.
Also, if you haven't checked out the Wikipedia article on REST, I strongly encourage you to do so. Finally, another good, classic read on REST is How I Explained REST To My Wife. Enjoy.

Related

Defining right API endpoint REST/RPC

I am developing an API in a microservice for Invoice entity that takes in input a list of Purchase Order Item (i.e. PO Item) identifiers for ex. PO# + productIdentifier together can be used to identify a POItem uniquely. The response of the API is the invoiced quantity of each PO Item.
Input Model -
input GetInvoicedQuantityForPOItemsRequest {
poItemIdentifierList : POItemIdentifierList
}
Structures
list POItemIdentifierList {
member : POItemIdentifier
}
structure POItemIdentifier {
purchaseOrderNumber : String,
productIdentifier : Long
}
Invoiced Quantity of a POItem = SUM of Quantity of Invoice Items created from that PO Item.
Note : A single PO can be used to create multiple Invoices. An Invoice can be created from multiple POs.
I am quite new to REST and so far we have been using RPC endpoints in our legacy service. But now i am building a new service where i am defining endpoints in REST format (for ex. CreateInvoice has been changed to POST /invoice) and I need some suggestions from Stack Overflow community what would be the right approach for defining the REST endpoint of this API or should we keep it in RPC format itself.
RPC endpoint for this API in legacy system : POST /getInvoicedQuantityForPOItems
Our first attempt on REST for this is : POST /invoice/items/invoicedQuantityForPOItems. But this URI does not look like a Noun it is a Verb.
this URI does not look like a Noun it is a Verb.
REST doesn't care what spelling conventions you use for your resource identifiers.
Example: this URI works exactly the same way that every other URI on the web works, even though "it looks like a verb"
https://www.merriam-webster.com/dictionary/post
The explanation is that, in HTTP, the semantics of the request are not determined by parsing the identifier, but instead by parsing the method token (GET, POST, PUT, etc).
So the machines just don't care about the spelling of the identifier (besides purely mechanical concerns, like making sure it satisfies the RFC 3986 production rules).
URI are identifiers of resources. Resources are generalizations of documents. Therefore, human beings are likely to be happier if your identifier looks like the name of a document, rather than the name of an action.
Where it gets tricky: HTTP is an application protocol whose application domain is the transfer of files over a network. The methods in HTTP are about retrieving documents and metadata (GET/HEAD) or are about modifying documents (PATCH/POST/PUT). The notion of a function, or a parameterized query, doesn't really exist in HTTP.
The usual compromise is to make the parameters part of the identifier for a document, then use a GET request to fetch the current representation of that document. On the server, you parse the identifier to obtain the arguments you need to generate the current representation of the document.
So the identifier for this might look something like
/invoicedQuantityForPOItems?purchaseOrder=12345&productIdentifiers=567,890
An application/x-www-form-urlencoded representation of key value pairs embedded in the query part of the URI is a common spelling convention on the web, primarily because that's how HTML forms work with GET actions. Other identifier conventions can certainly work, though you'll probably be happier in the long term if you stick to a convention that is easily described by a URI template.

HTTP Verbs, WebAPI

I would like to know the usage scenario of POST vs PUT in a WebAPI . I know the basic concepts that POST is for creating resource and PUT is for updating resource but not able to fully understand why we need a PUT over a POST.
I have 2 WebAPI methods which creates/updates data to my SQL store
1. CreateUser(UserDto)
2. UpdateUser(UserDto)
UserDto contains userId, username and email.
I can use POST for both CreateUser and UpdateUser methods which creates and updates user to my store.
Then what is the real advantage of using POST for CreateUser and PUT for updateuser? Is it just a standard/convention?
Thank you
POST always creates something new. PUT updates a existing thing. It is a convention.
You should have:
POST /users : to create a new user. The payload should not include the ID
PUT /user/(id) : to replace a user DTO with the data in the payload. Again, the payload should not contain an user id
PATCH /user/(id): to update specific members of the user, but the id.
It is a design convention, like software design patterns, to make it easy to communicate and understand by whoever has to consume the API.
POST is usually used to add a new resource into collection of resources.
Like this: POST /users.
This operation is NOT idempotent and it will have a side effect at each call.
While PUT is usually used with a replace semantic and you know the exact resource which you want to replace.
Like this: PUT /users/1.
This operation is idempotent and it will not have any side effects on subsequent calls.

Laravel DELETE request as API

When you want to delete an item from the db, I know that you can use /resource/{id} and use the contrller#destroy action.
What is the advantage of passing a parameter in the URL as oppose to send a DELETE request and pass the parameter $id via an Input?
You can certainly do both, but the first method (using the dedicated /resource/{id} URL) is following the RESTFUL design pattern. Here is a very good video on that.
To highlight some important points:
We avoid verbs in URLs, unless they're used for very specific actions. We should try to use nouns instead if it's possible, so a url like /resource/deleteis not advisable.
When someone used to the REST way of communicating with an API uses 'DELETE' on the /resource url, he/she expects to delete ALL resources. If he/she uses it on /resource/{id}, then only that specific item should be removed.
Hope this made sense =)

Zend Framework 1 Ajax

Could somebody please suggest me a good beginner tutorial of using Ajax with Zend 1.I have been searching the net for some of this tutorials, but couldn't find an understandable one.In some they say you have to create a .json.phtml file for json response, the others don't.I am very confused about all these ajax calls with Zend Framework 1. Would be very grateful.
Well there really are some basic things.
Get your data (from DB, file, in-code array, whatever)
Get the controller helper
Send the JSON response
And that's it. OK, not exactly but basically yes!
Provided you have the data in $data:
$this->_helper->json($data, true);
will return a JSON response. The documentation is here.
Now there is the other notion of a Context Switch and AjaxContentHelper which:
The ContextSwitch action helper is intended for facilitating returning different response formats on request. The AjaxContext helper is a specialized version of ContextSwitch that facilitates returning responses to XmlHttpRequests.
To enable either one, you must provide hinting in your controller as to what actions can respond to which contexts. If an incoming request indicates a valid context for the given action, the helper will then:
Disable layouts, if enabled.
Set an alternate view suffix, effectively requiring a separate view script for the context.
Send appropriate response headers for the context desired.
Optionally, call specified callbacks to setup the context and/or perform post-processing.
Something like this:
$contextSwitch = $this->_helper->getHelper('contextSwitch');
$contextSwitch->setDefaultContext('json');
$contextSwitch->addActionContext('index', array('xml','json'))->initContext();
$contextSwitch->addActionContext('get', array('xml','json'))->initContext();
$contextSwitch->addActionContext('post', array('xml','json'))->initContext();
$contextSwitch->addActionContext('put', array('xml','json'))->initContext();
$contextSwitch->addActionContext('delete', array('xml','json'))->initContext();
$contextSwitch->addActionContext('head', array('xml','json'))->initContext();
You don't really need a tutorial I think. All you need is a good basic knowledge of how the web works internally and to read the Zend Documentation. Anyway here is some tutorial on ContextSwitch.

Combining GET and POST in Sinatra (Ruby)

I am trying to make a RESTful api and have some function which needs credentials. For example say I'm writing a function which finds all nearby places within a certain radius, but only authorised users can use it.
One way to do it is to send it all using GET like so:
http://myapi.heroku.com/getNearbyPlaces?lon=12.343523&lat=56.123533&radius=30&username=john&password=blabla123
but obviously that's the worst possible way to do it.
Is it possible to instead move the username and password fields and embed them as POST variables over SSL, so the URL will only look like so:
https://myapi.heroku.com/getNearbyPlaces?lon=12.343523&lat=56.123533&radius=30
and the credentials will be sent encrypted.
How would I then in Sinatra and Ruby properly get at the GET and POST variables? Is this The Right Way To Do It? If not why not?
If you are really trying to create a restful API instead if some URL endpoints which happen to speak some HTTP dialect, you should stick to GET. It's even again in your path, so you seem to be pretty sure it's a get.
Instead of trying to hide the username and password in GET or POST parameters, you should instead use Basic authentication, which was invented especially for that purpose and is universally available in clients (and is available using convenience methods in Sinatra).
Also, if you are trying to use REST, you should embrace the concept of resources and resoiurce collections (which is implied by the R and E of REST). So you have a single URL like http://myapi.heroku.com/NearbyPlaces. If you GET there, you gather information about that resource, if you POST, you create a new resource, if you PUT yopu update n existing resource and if you DELETE, well, you delete it. What you should do before is th structure your object space into these resources and design your API around it.
Possibly, you could have a resource collection at http://myapi.heroku.com/places. Each place as a resource has a unique URL like http://myapi.heroku.com/places/123. New polaces can be created by POSTing to http://myapi.heroku.com/places. And nearby places could be gathered by GETing http://myapi.heroku.com/places/nearby?lon=12.343523&lat=56.123533&radius=30. hat call could return an Array or URLs to nearby places, e.g.
[
"http://myapi.heroku.com/places/123",
"http://myapi.heroku.com/places/17",
"http://myapi.heroku.com/places/42"
]
If you want to be truly discoverable, you might also embrace HATEOAS which constraints REST smentics in a way to allows API clients to "browse" through the API as a user with a browser would do. To allow this, you use Hyperlink inside your API which point to other resources, kind of like in the example above.
The params that are part of the url (namely lon, lat and radius) are known as query parameters, the user and password information that you want to send in your form are known as form parameters. In Sinatra both of these type of parameters are made available in the params hash of a controller.
So in Sinatra you would be able to access your lon parameter as params[:lon] and the user parameter as params[:user].
I suggest using basic or digest authentication and a plain GET request. In other words, your request should be "GET /places?lat=x&lon=x&radius=x" and you should let HTTP handle the authentication. If I understand your situation correctly, this is the ideal approach and will certainly be the most RESTful solution.
As an aside, your URI could be improved. Having verbs ("get") and query-like adjectives ("nearby") in your resource names is not really appropriate. In general, resources should be nouns (ie. "places", "person", "books"). See the example request I wrote above; "get" is redundant because you are using a GET request and "nearby" is redundant because you are already querying by location.

Resources