Best practice of creation GET methods with many parameters(filters) - spring

I have the GET method in my Spring REST controller. This method returns the list of users by the filter.
I have a few ways to implement it:
Add #PathVariable like - /users/{type}/{age}/{name}/...(bad approach in this case)
Add #RequestParam like - /users?type=type,age=age,name=name...(usual approach in this case)
Use RequestDto (the best approach) like
public class UsersRequestDto {
private String type;
private int age;
private String name;
...
}
But I can not use GET method for this. I must use POST method with #RequestBody
And it breaks the rules. My method doesn't change state and doesn't create any entities. It workes as the GET method but in reality, it is POST.
And I have 2 ways:
Use the GET method with many parameters
Use the POST method with DTO which works as the GET method and confuses users.
Which way is better?

Short version: you might be looking for How to bind #RequestParam to object in Spring. (See also: https://stackoverflow.com/a/16942352/54734 )
On the web, we would have an html form with a GET action. When the form is submitted, the browser would process the input controls and create the application/x-www-form-urlencoded representation of the form data. For a GET action, that representation is used as the query string.
Using GET, and encoding all of the information into the query string, allows us to take advantage of general purpose caching of the results.
But the query parameters aren't accessible by themselves - they are actually embedded within the larger context of the HTTP request. We don't usually see that because, once again, general purpose components can do a lot of the heavy lifting.
So we don't see the parser that extracts the target-uri from the request, or the parser that splits the target URI into its separate components, or the parser that splits the query part into a sequence of key value pairs....
In general, what we do is ride the "general purpose" implementation as far as we can, then get off and do the rest of the work ourselves. If the framework offered no better support for object mapping, that could mean implementing that mapping ourselves.
So if our framework lacked the capability to map the query string directly to an object representation, we would hand roll that part of the implementation ourselves (either by copying each parameter "by hand", or writing our own reflection code to do the mapping automagically).
But it seems that Spring has that capability already built into it; and that it is the default option (no annotation required); you just have to be sure that the object implementation provides the interface that Spring needs to execute the mapping.

How many different parameters are you including in your query?
Personally, I prefer the option of a GET method with many different parameters. It has other benefits such as being cacheable as well. Also, compare it to something like a the URL that a Google search generates - lots of query string parameters.
The POST option feels dirty - it's a violation of what a POST should actually do (creating or updating a resource).
See these discussions: https://softwareengineering.stackexchange.com/questions/233164/how-do-searches-fit-into-a-restful-interface and REST API Best practices: Where to put parameters?

1st of all when you are using RequestParam then key will be added with & symbol not with comma(,) .
when you want to filter ( as you have mentioned) something then best approach would be to use RequestParam.
To minimize the code you can opt to "MultiValueMap" or "HttpservletRequest" .
1)HttpServletRequest
#GetMapping("/user")
public List<User> getFilteredUser(HttpServletRequest httpservlet)
httpservlet.getQuesryString() //will return all request param.
2)MultiValueMap
#RequestParam MultiValueMap<String,String> params
NOTE:- Generally POST is for create/update record.

Related

Spring Boot REST - how to POST/PATCH in many-to-many relationship

I Have a problem with adding many-to-many relationship in my REST api.
Let' say we have two entities with many-to-many relationship - Employee and Task (employee have Set<Task> and task have Set<Employee>).
Some specific task is accessible via this endpoint:
http://localhost:8080/api/tasks/2
Tasks assigned to Employee with id 88 is accessible via:
http://localhost:8080/api/employees/88/tasks
The goal is to POST/PATCH this link to the endpoint.
Could you give me a hint, how this endpoint should look like in controller?
I tried something like this, but it's not working.
#PatchMapping("/{employeeId}/tasks")
public Task addTask(#RequestBody Task task, #PathVariable Long taskId) { ... }
Second problem - I would linke to use Postman. Could you tell me which Content-Type should I choose? And how should this link be formatted?
Looking forward for your answers!
EDIT
Do I have to add another constuctor that takes uri?
By definition the PATCH method applies a partial update to a given resource, while the PUT method is used to replace a given resource entirely. The keyword here is that both PATCH and PUT are specific to a given resource.
The POST method is used to create a new resource.
Therefore, it makes sense that if you want to update just a few fields in your resource and you don't need to update it entirely, to use the PATCH method instead of the PUT method.
The PATCH request body describes how the resource shall be updated, with a series of operations. One format that you can use to describe these operations is the JSON Patch.
Since the PATCH operation is specific to a given resource, and making use of the json-patch library, your controller method should be something like:
#PatchMapping("/{employeeId}/tasks/{taskId}")
public Task updateTask(#RequestBody JsonPatch taskPatch, #PathVariable Long employeeId, #PathVariable Long taskId) { ... }
Note that this a different thing than POST, with a different method (updateTask). For example, if you want to update one field from your task resource (given by taskId), your jsonPatch sent in the request body from your client (can be Postman) would be something like
[{
"op":"replace",
"path":"/field",
"value":"newValue"
}]
There are different operations, such as add, remove, replace, copy and test.
Now in your code you will need to apply this patch to the existing resource. This reference shows how can you do that:
https://www.baeldung.com/spring-rest-json-patch
I hope this helps.

What is the most ideal way to add validation to Spring REST Service Request Parameters

I have a Spring-REST service that has support for GET, POST, PUT requests and they all have been mapped in a #Controller (Sorry for stating the obvious, just new to the technology)
Now each method (RequestMapping) has its own parameters like one takes in id
other takes in name and third one takes in secretKey
I want to validate these request parameters in my own custom manner
Now tried looking up as many tutorials online as possible but did not come across any solution that would best serve my situation.
Here is what I mean:
I saw a tutorial for POST request parametes by using #RequestParam or #Valid but that does not work for GET requests (That's what I read)
I saw most people recommending JS303 but that does not suit my need as I need to validate the secretKey against the DB (id and name may be I can use JSR #Size but even the id and name would need further validation)
I also saw some recommending #Validator but that would mean I will need a validator class for each and and every parameter like IdValidator, NameValidator etc
Here is something that I am hoping to accomplish:
One Validator (Can be either something that implements Validator or COnstraintValidator) however its implementation should cater to validation of all kinds of requests (can definitely have multiple methods inside it based on what request its validating) and should throw a CustomException that I created
I am not posting what I have tried because it is actually too much code that I just copy pasted from what I searched online. If you want I can post the links that I copied the code from.
P.S. I am not an expert on Spring, but trying to learn

Using Spring Data REST to handle complex aggregate roots

Right now I can't get the concept behind Spring Data REST if it comes to complex aggregate roots. If I understand Domain Driven Design correctly (which is AFAIK the base principle for spring data?), you only expose aggregate roots through repositories.
Let's say I have two classes Post and Comment. Both are entities and Post has a #OneToMany List<Comment> comments.
Since Post is obviously the aggregate root I'd like to access it through a PostRepository. If I create #RepositoryRestResource public interface PostRepository extends CrudRepository<Post, Long> REST access to Post works fine.
Now comments is renderd inline and is not exposed as a sub resource like /posts/{post}/comments. This happens only if I introduce a CommentRepository (which I shouldn't do if I want to stick to DDD).
So how do you use Spring Data REST properly with complex domain objects? Let's say you have to check that all comments does not contain more than X characters alltogether. This would clearly be some invariant handled by the Post aggregate root. Where would you place the logic for Post.addComment()? How do you expose other classes as sub resources so I can access /posts/{post}/comments/{comment} without introducing unnecessary repositories?
For starters, if there is some constraint on Comment, then I would put that constraint in the constructor call. That way, you don't depend on any external validation frameworks or mechanisms to enforce your requirements. If you are driven to setter-based solutions (such as via Jackson), then you can ALSO put those constraints in the setter.
This way, Post doesn't have to worry about enforcing constraints on Comment.
Additionally, if you use Spring Data REST and only define a PostRepository, since the lifecycle of the comments are jointly linked to the aggregate root Post, the flow should be:
Get a Post and its collection of Comment objects.
Append your new Comment to the collection.
PUT the new Post and its updated collection of Comment objects to that resource.
Worried about collisions? That's what conditional operations are for, using standard HTTP headers. If you add a #Version based attribute to your Post domain object, then every time a given Post is updated with a new Comment, the version will increase.
When you GET the resource, Spring Data REST will include an E-Tag header.
That way, your PUT can be conditionalized with an HTTP If-Match: <etag> header. If someone else has updated the entity, you'll get back a 412 Status code, indicating you should refresh and try again.
NOTE: These conditional operations work for PUT, PATCH, and DELETE calls.

Best way to represent object views (summary, detail, full etc) in Spring based REST service

I am working on a REST service which uses Spring 4.x. As per a requirement I have to produce several different views out of same object. Sample URIs:
To get full details of a location service: /services/locations/{id}/?q=view:full
To get summary of a location service: /services/locations/{id}/?q=view:summary
I have thought of two solutions for such problem:
1. Create different objects for different views.
2. Create same object, but filter out the fields based on some configuration (shown below)
location_summary_fields = field1, field2
location_detail_fields = field1, field2, field3
Could someone help me to understand what could be an ideal solution? I am not aware of any standard practice followed for this kind of problems.
Thanks,
NN
In my opinion the best option is to use separate POJOs for different views. It's a lot easier to document it (for example when you use some automated tools like Swagger). Also you've to remember that your application will change after some time, and then having one common POJO could make troubles - then you'll need to add one field to one service and don't expose it through another.
See this article on how google gson uses annotations to convert a Java Object representation to a json format : http://www.javacreed.com/gson-annotations-example/
Since you want two different representations for the same object you could roll your own
toJson method as follows :
a) Annotate each field of you model with either #Summary, #Detail or #All
b) Implement a toJson() method that returns a json representation by examining the annotations for the fields and appropriately using them
If you need an XML representation same thing, except you would have a toXML().

ActionMethodSelectorAttribute equivalent in ASP.NET Web API?

Is there a Web API equivalent to the MVC ActionMethodSelectorAttribute?
My specific purpose is this: I have, for example, a ResourceController and when I POST to the controller, I'd like to be able to receive a single resource (Resource) or a list (IEnumerable<Resource>).
I was hoping creating two methods with different parameters would cause the deserialization process to do some evaluation but this doesn't seem to be the case (and frankly, I don't think it's efficiently realistic with the combination of content negotiation and the fact that many data formats, like JSON, make it difficult to infer the data type). So I originally had:
public HttpResponseMessage Post(Resource resource) {...}
public HttpResponseMessage Post(IEnumerable<Resource> resources) {...}
...but this gets the "multiple actions" error. So I investigated how to annotate my methods and came across ActionMethodSelectorAttribute but also discovered this is only for MVC routing and not Web API.
So... without requiring a different path for POSTing multiple resources vs. one (which isn't the end of the world), what would I do to differentiate?
My thoughts along the ActionMethodSelectorAttribute were to require a query parameter specifying multiple, which I suppose is no different than a different path. So, I think I just eliminated my current need to do this, but I would still like to know if there is an equivalent ActionMethodSelectorAttribute for Web API :)
I haven't seen a replacement for that method (there is an IActionMethodSelector interface but it is internal to the DLL). One option (although it seems like it might be overdoing it) is to overload the IHttpActionSelector implementation that is used.
But changing gears slightly, why not always expect an IEnumerable<Resource>? My first guess is that the collection method (that takes IEnumerable<Resource>) would simply loop and call the single value (just Resource) function?

Resources