DTO stands for Data Transfer Object. The advantage of using DTOs on RESTful APIs is that they can help hiding implementation details of domain objects (aka. entities). Exposing entities through endpoints can become a security issue if we do not carefully handle what properties can be changed through what operations.
As an example, let's imagine a Java API that exposes user details and accepts user updates through two endpoints. The first endpoint would handle GET requests and return user data, and the second endpoint would accept PUT requests to update these details. If this application didn't take advantage of DTOs, all the properties of the user would be exposed in the first endpoint (e.g. password) and the second endpoint would have to be very selective on what properties would accept when updating a user (e.g. not everybody can update the roles of a user).
To overcome this situation, DTOs can come in handy by exposing only what the first endpoint is intended to expose, and by helping the second endpoint to restrict what it accepts. This characteristic helps us to keep the integrity of the data in our applications.
You won't need to map your persistence entities to DTOs and vice versa manually. There are many mapping frameworks you can use to do it. For instance, have a look at MapStruct, which is annotation based and works as a Maven Annotation Processor. It works well in CDI(context and dependency injection) and Spring-based applications.
Also consider Lombok to generate getters, setters, equals(), hashcode() and toString() methods for you.
JSR-303 bean validation has become the validation standard in the Java world. Bean validation API provides an object level constraint declaration and validation facility for the Java application developer, and a constraint metadata repository and query API. Spring bean validation allows us to use these bean validation constraint directly on the Java beans. There are several benefits of this approach
- No need for separate validation configurations.
- Constraints are straight on the domain models.
$ curl -X POST "http://localhost:8090/api/employers" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"firstName\": null, \"lastName\": \"Mario\", \"matricule\": \"Mat-2015632\"}"
{
"status": "400 BAD_REQUEST",
"error": "FORM_VALIDATION_ERROR",
"message": "1 error(s) found while trying to validate form",
"details": {
"firstName": ["must not be blank"]
}
}
To properly document the available endpoints in your REST API, which endpoints there are, what they can do, what they need as input parameters and what they will provide as output. A popular standard, that is used for this, is Swagger.
After running the application, go to http://localhost:8090/api/swagger-ui.html. If you see a blank screen, you might have to refresh once, but normally you’ll see a screen like this:
Let's make simple requests using CURL:
$ curl -X GET "http://localhost:8090/api/employers/search?name=toto" -H "accept: application/json" -H "Accept-Language: fr"
On peut pas trouver l emplyeur toto
$ curl -X GET "http://localhost:8090/api/employers/search?name=toto" -H "accept: application/json" -H "Accept-Language: en"
Could not find employee toto
$ curl -X GET "http://localhost:8090/api/employers/search?name=toto" -H "accept: application/json"
On peut pas trouver l emplyeur toto
So as you see, responses are different based on value of “Accept-Language” header passed in the request. This way, we don’t need to check what was passed in the request in each controller method, and then pass it further to service layers. We now can do this in one single place, which is CustomLocaleResolver class.
when you execut GET request to our find all users endpoint, you’ll get next result:
So, it takes about 3325 milliseconds to get all users. And this is an horrible scenario for real use case !!
So here Spring Cache can solve our issue!
Now when you restarted the server and make GET request to fetch all users — first time it will take those 3 with something seconds to get data back to you. Because firstly it will check the cache, and will see that it is empty, and will execute the method, with 3 seconds delay. But all further requests to findAll() will be executed much much faster, because method will not be executed, since requested data was cached previously and will be taken for you from the cache.
As you see, the request execution time is much less, than before. It’s simply because the method findAll() is not executed, since the data is already in cache, that’s why it works so fast
Behavior-Driven Development aka BDD, its intent is to enable developers to write high-level use cases in plain text that can be verified by non-technical stakeholders, and turn them into executable tests, written in a language called Gherkin.
just 5 step recipe for making it work :
- Configure the build script
- Write the Gherkin tests
- Implement the Gherkin steps test code
- Implement the feature being tested
- Run the Gherkin tests and get the result
Results of test are saved in : target/cucumber-reports/index.html
- Spring Boot REST Internationalization
- REST API - DTOs or not?
- Automatically Mapping DTO to Entity on Spring Boot APIs
- How To: Add caching support to your Spring Boot application
- Rédiger des spécifications - La syntaxe Gherkin
- Spring Boot 1.4: Gherkin tests
to see
https://univers-architecture.com/2017/12/11/tutoriel-integration-de-cucumber-avec-spring-boot/