Improvements in CUBAs REST API v2
Improvements in CUBAs REST API v2
The release of the CUBA platform 6.3 has brought huge changes. Take a second look at the platform and its REST API features in this article.
Join the DZone community and get the full member experience.Join For Free
Along with the application components, there is another interesting feature that is a part of the 6.3 release of the CUBA platform. It deals with the REST API feature. In this post, we will have a deeper look into it and see the differences and potential benefits of it.
Once Upon a Time, There Was a Blog Post
Last year I did a blog post about the REST-API implementation of the CUBA platform. In the 6.3 release, the generic REST API has been more or less redesigned completely. Due to the massive changes, it is worth taking another look into it.
Just to give you a quick recap on what the old (v1) REST API was all about, here’s a small list of features that have been included:
- (API-)user authentication.
- CRUD on single entity instances.
- Get a list of entities through a JPQL query definition.
- Execute business logic through service calls via HTTP.
- Upload/Download files from file storage.
- Create views to customize entity representation retrieval.
In the new implementation, the feature list pretty much remains the same, but the way to execute the different features changed quite a bit.
Let’s look at the things that have changed.
Changes on CUBA's REST API
First, the authentication mechanism has changed to the OAuth2 mechanism. Next, the CRUD operations on the entity level have become much more “RESTful” towards a de-facto standard resource naming, which is implemented by most of the major web application frameworks. This also includes usage of the most common HTTP verbs.
Authenticate via OAuth2
The first major change concerns the login mechanism. The v1 login mechanism was based on a homegrown login mechanism. In version 2, it is a fully compatible implementation of the OAuth2 specification. The login mechanism basically goes like this (to communicate to the REST API I use the cmd line tool Httpie):
The API client sends a POST request to the server to get an access token. In order to accept the request, it has to be executed with basic auth in place (client:secret). These hard-coded client secrets can be configured in the app.properties of the CUBA application (cuba.rest.client.id and cuba.rest.client.secret). In the body, a form is sent with the actual credentials of the user.
The result is a JSON with a
access_token in it. This token has to be used for further requests in the
Authorization header like this:
Here is the full example:
CRUD Operations on Entities
With the access token, we are able to consume the REST API by passing the token to every request. One example of this is that we can create a request that will list all customers that the user is allowed to see (you can download the example app from GitHub).
This structure is basically the same that all of the major web frameworks support nowadays. CUBA offers a swagger API description, which is a very cool feature to get familiar with the API structure.
Predefined Queries Instead of per-request-JPQL
One thing that changed dramatically is the feature to execute arbitrary JPQL queries. In version 1, the client could create a request that had a JPQL in it, which should get executed. This exposure of the database query language in the API is something that might be valuable for integration purposes, where you control the sender as well as the receiver. But from an API point of view, it is like exposing detailed information about the implementation structure to the outside world.
Since in v2 the API moves much more towards a public facing API facility, this feature was removed. The replacement for that is that you can define something that is very similar to named queries in the JPA world for the API on the server. These named queries act as the abstraction mechanism to the API consumer. This way the customer is not forced to know about the internal entity structure. Instead, it only has to know about the name of the query and the parameter that this query might have.
Here’s a small example of that definition:
It can be created in a file within your war file or in an external config folder on the server, but the main idea is that it has to be created in advance, so the client is not forced to define these details (which also means that the consumer can’t either). Generally, I think this is a very good way of defining an API abstraction.
Batch Mode of Entities is Gone
Another thing to notice is that it is not possible to make a bulk import out of the box anymore. In the previous version is was possible to POST instances with the following JSON structure:
In the commitInstances array, a list of entities can be created and inserted into the database within one database transaction.
Due to the change towards the de-facto standard REST URI resource pattern, this is no longer possible, because the instances are treated like resources. When an instance is created, you’ll get back an HTTP response
201 - created with a corresponding
LocationHeader that points to this newly created resource (in this case - the entity). Something like this is hardly possible in a batch mode, because the response can’t point to the created resource. Also, it would be problematic to handle validation errors in this case (which have been included in 6.4 with bean validation).
This is just something to know. It would be possible to create a service that brings back this feature of doing bulk create, but with that, you would get back to the RPC-based approach of the API (which is exactly the point of the v2 API to drift away from that, at least in my understanding of it).
Using the REST API
There are several examples in the docs on how to communicate with the new API. Therefore I will not go into detail about the different CRUD operations, service invocations, etc.
Instead, I would like to show you two little tools that I found quite appealing to deal with the API on a day-to-day basis. Above we have already seen the command line based tool called httpie. Httpie is just like cURL but optimized for ease of use. cURL has the downside that certain operations on HTTP (like form submit) are fairly verbose when you want to type them.
This is where Httpie kicks in. Let’s look at the Login process in cURL:
With Httpie it changes to this:
It gives you a fairly nice tool to do the easy HTTP things. But for some people, fiddling around with the command line all the time is not the preferred way of doing it (including myself), so there is one other tool I used lately.
Explore Your API With Postman
The next thing that I use really often for interacting with the CUBA API is the tool Postman. Postman is a UI based HTTP client that started out as a Chrome plugin and emerged to a full fletched application. It is built on Electron, which is pretty cool.
Postman has the possibility to create “request collections.” These are groups pre-defined requests to your API. You can just select one and “send” it.
Additionally, there is another building block called “environments.” An environment is the possibility to parameterize your collections. One example of this might be the server URL. When you have different deployments of your application- say, in dev, testing, and production- you can create three environments with the definition of a particular variable that you use in your requests.
Here’s an example of the UI of Postman:
To give you an easy start with the tool, I created the Postman collection as well as the Postman environment within the GitHub example. You can just import it into your Postman client and start fiddling around with it.
Within the shared collection, I used it not for automated testing, but instead used the scripting facility to do some kind of automation. When you look at the Tests tabs of the Login request, you will find that I’ve programmatically created an environment variable within postman called ‘access_token’:
This script basically checks if the response is valid, and if it is, it will set the environment variable like this:
With that everywhere in Postman, the variable can be used just by using the double-curly braces notation (like shown below in the Authorisation header).
Using Swagger Description in Postman
If you want to try out all features of the v2 API in Postman, there is even an easier way to do so, instead of creating all the requests by hand. Postman is able to import not only the collections in their format, but read the Swagger format as well. With this, you can just point Postman to the URL of the YAML description of CUBA.
With that, you have imported the whole description of Swagger into your app and can start uploading files, doing service requests, and more.
Published at DZone with permission of Mario David . See the original article here.
Opinions expressed by DZone contributors are their own.