Spring Data Rest and Spring MVC hateoas - spring

I have an angular app, requesting data from a Spring Boot backend with Spring Data Rest. Requests to repositories generate responses with HATEOAS structure. But when I ask from Spring MVC controller, the response is indifferent structure(natural).
Is there any example where I can achieve the same structure on a particular controller request? I believe I should implement HATEOAS, but haven't seen a single example.

Find official example here.
The return value of your controller method should be wrapped in EntityModel or CollectionModel, so the JSON should be in HAL format.
#PostMapping("/orders")
ResponseEntity<EntityModel<Order>> newOrder(#RequestBody Order order) {
order.setStatus(Status.IN_PROGRESS);
Order newOrder = orderRepository.save(order);
return ResponseEntity //
.created(linkTo(methodOn(OrderController.class).one(newOrder.getId())).toUri()) //
.body(assembler.toModel(newOrder));
}

Related

Why do we need jackson databind?

I am new in Spring MVC. My question is, why do we need jackson databind? Because We can receive the Request Params by #ModelAttribute and requests through http PUT or POST by #RequestBody. I can't find a reason why we need jackson databind to convert json/xml to POJO or vice versa.
Thanks.
Why do we need jackson databind?
Because representing structured data is much easier using XML (or JSON) than using simple name-value pairs.
Because it is more convenient to send and receive JSON from the client side when you are doing AJAX.
Because once you have to deal with sending and receiving JSON or XML in the server side Java app, it is more convenient to deal with structured data as POJOs.
None of the above points mean you have to use a binding. There are other ways of dealing with each of the above. But many Java developers think that data bindings the better way to go: more efficient in terms of developer time, and more reliable. Especially if you are implementing services with a complex APIs. That's why they are popular.
And as other answers/comments point out, if you are using #RequestBody, then that is using a binding library under the hood to give you the POJOs. In the case of Spring, it is Jackson that is being used.
By default, when an endpoint expects a JSON document as input and a given controller method argument is annotated with #RequestBody, Spring will use Jackson databind features to map the incoming JSON document to a Java object. You don't need to use the Jackson's ObjectMapper directly, as Spring does it for you.
For example purposes, consider the following HTTP request to create a comment:
POST /comments HTTP/1.1
Host: example.org
Content-Type: application/json
{
"content": "Lorem ipsum"
}
And the following class which represents a comment:
#Data
public class Comment {
private String content;
}
A #RestController to handle such request would be like:
#RestController
#RequestMapping("/comments")
public class CommentController {
#PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Foo> createComment(#RequestBody Comment comment) {
// By default, Spring will rely on Jackson databind to map the incoming
// JSON document to the comment argument annotated with #RequestBody
...
}
}
If you are interested in the Spring component that maps the incoming JSON document to a Java object, have a look at the MappingJackson2HttpMessageConverter class:
Implementation of HttpMessageConverter that can read and write JSON using Jackson 2.x's ObjectMapper.
This converter can be used to bind to typed beans, or untyped HashMap instances.
By default, this converter supports application/json and application/*+json with UTF-8 character set. [...]
If you are creating a HTTP API and exposing resources that can be manipulated with JSON representations, it's unlikely you'll use #ModelAtribute. Such annotation is particularly useful when you are dealing with web views.
When you get some request in some data types like json/xml, the Spring MVC platform will try to deserialize this request attributes in some model object of your project.
But the platform itself don't provide a des-serialize implementation out of the box. So it will try to use some des-serializer provider in the classpath like jackson, jersey, gson, etc.
As you said - is possible to use #ModelAttribute - but this annotation is a better option to a request from a form view in the front-end. In cases rest json/xml requests, the #ModelAttribute won't be able to convert correctly the received data to a business class of your program.

For spring project, Do i need to inject pagerequest object?

I read some articles conecerning clean architecture.
These articles say that business layer should not know how to solve domain knowledge directly. (only what to do)
PageRequest object is provided by spring framework.
And this object implements Pageable interface.
My question is...
Do i create the Pagerequest in business layer (service)
or inject it to the layer?
You said the PageRequest / Pageable object is provided by Spring, so - if you are using Spring MVC - I would expect something like the following on controller level:
#RequestMapping(method = ..., path = ..., produces = ...)
public ... readSomethingPaged(#PathVariable String ..., Pageable pageable) {
...
}
Then of course you have to pass this Pageable (created automagically by Spring using the request parameters page=...&size=...&sort=...) through your service layer down to the place you are getting the data from. Within Spring (Boot) a Spring Data JPA repository comes in handy. It accepts the Pageable created by the controller and returns the appropriate data.
Or what exactly do you mean with "Do i create the Pagerequest in business layer"?
If you really have to create your own PageRequest it has to be done before the repository is called, then imho not the service itself but the controller / a facade should be responsible for that.

How to correctly implement a REST service that returns a list of images using Spring MVC\Boot?

I am not so into RESTful web services and I have the following doubt about how correctly return a list of image using RESTful paradigm.
I am working on a Spring Batch application (but it is the same thing that uses Spring MVC for this purpose). I have this controller method that returns to the client a list of images as a list of array of byte converted into a JSON message.
I implemented it in this way:
#RequestMapping(value = "getAllImagesByRoomId",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<byte[]>> getAllImagesByRoomId(Long roomId) throws DataAccessException {
log.debug("getAllImagesByRoomId START");
List<byte[]> result = roomMediaService.getRoomImageListById(roomId);
log.debug(result.toString());
log.debug("getAllImagesByRoomId END");
return ResponseEntity.ok(result);
}
It works pretty fine and my client retrieve the images from the returned JSON.
But from what I have understand it is not RESTful conception because in the REST principals I have to return a JSON response which contains hyperlinks to all the individual images, and then the client can follow those links and grab the images.
So in this case I will have a service handle request to a single image (represented by an URL) and that return an image as an array of byte. but for the service that return a list of images I have my REST service that return a list of URI represented the single image served by the first service.
Could be a good idea?
Spring Data REST
What is and isn't Restful is constantly debated. Generally speaking, it involves Stateless HTTP requests that target a particular resources, via URI, and the response usually conforms to JSON. Not all of these are hard and fast rules but that is what you'll typically see.
An improvement on the above approach is HATEOAS, which are the links you referred to.
You can easily generate Restful, HATEOAS endpoints via the Spring Data REST project. It handles most of the painful configuration and lets you focus on the resources you wish to expose.

How to return representations of associations in a Spring Data REST resource?

There are following URLS - /users/2/profile , /users/2/userPosts
I need to concat output of both Spring Data REST results in server side and build single JSON from them and send on different URL /users/2/custom.
So, I am thinking to make 2 calls to SDR urls from Spring MVC, can we do this using RestTemplate and some JSON concat utility , here server and database is on same machine so RestTemplate will probably have localhost
An example will help
You might rather want to look into the projections feature of Spring Data REST which allows you to craft custom responses by using interfaces as described in this blog post.
As both properties (profile and userPosts) seem to be associations of a user item resource it should be sufficient to do something like this:
#Projection(types = User.class)
interface UserWithDetails {
// List getters for basic properties you want to expose…
// Add dedicated getters for associations to be included
Profile getProfile();
List<Post> getUserPosts();
}
Clients can now pass a projection parameter to the resources exposed to see the expanded representation.
As an alternative, you can create these kinds of interfaces for Profile and Post and configure #RepositoryRestResource on the repositories for both of these types to contain excerptProjection = YourProjectionInterface.class. This will cause the projections to be rendered whenever an association is included in the response (i.e. an actually-linked-to-resource could be embedded).

Spring boot actuator - Implement custom metrics

I would like to implement custom metric or statistics to my spring boot rest web service using actuator but i am not able to find simple tutorials.
For example:
how to show how many times a certain controller was called and what exact parameter field was filled?
how can i create a metric that when its URL is called, it runs certain query and shows back a json with some result
This seems like a good scenario for AOP (Aspect Oriented Programing) as this will allow you to separate this statistic logic from the business logic.
Have a look at Spring doc for more info about AOP and how to achieve that with Spring.
You can then define a pointcut on your controller and have a service for counting (and probably then storing) the data.
Refer below link
AOP Example
For point two the solution is to create an endpoint class (it can be or not a rest controller class). For example:
#Component
#RestControllerEndpoint(id = "pfm-statistics")
public class StatisticsEndpoint {
#GetMapping(value = "/", produces = "application/vnd.openxmlformats-
officedocument.spreadsheetml.sheet")
#ResponseBody
public byte[] generateStatisticsAsExcel() {
...
Note that the ID is the path to be called from URL. We can create a simple endpoint too and just return a string if we want. In this case instead of #RestControllerEndpoint annotation we can use #Endpoint, as a side note, the id should always contain dash

Resources