Spring rest use of pathVariable and RequestParam - spring

With spring rest is there any reason to use request param?
For a search i don't know if i shoud use
#RequestMapping(value = "/lodgers/{searchParam}", method = RequestMethod.GET)
public Lodger getAllLogders(#PathVariable("searchParam") String searchParam)
or
#RequestMapping(value = "/lodgers/", method = RequestMethod.GET)
public Lodger getAllLogders(String searchParam)

As I use it, a path (pathVariables) points to a resource.
A queryParam (requestParam) results in a subset of a resource.
If you want certain users from /Users (e.g. beginning with "A", or lodgers named "Curt") this would be a subset, of all /Users and I see not a very good reason for having a special resource with that criteria, so I would use a queryParam here.

Related

Inject request URI RequestMapping

I'm working on a stubbing tool where a user can provide a list of endpoints and their associated JSON response. The idea is they will include a config file containing URIs and a directory of all stubbed responses. So essentially the config file will include the list of URI's that typically would be set using #RequestMapping if this was being built for a specific use case. Is there a way to have Spring send a success response even if the associated #RequestMapping doesn't exist?
Something similar to a SQL query e.g.
#RequestMapping(value = "/*", method = arrayOf(RequestMethod.POST))
fun sendResponse() : ResponseEntity<String> {
//Fetched correct response from interceptor
return ResponseEntity<String>
}
Found out the answer. You need to use #RequestMapping(value = "/**", method = arrayOf(RequestMethod.POST)).

how to apply post method to all request mappings in spring

How i can access to request POST data from different url-s to one controller method, for example I have /countries & /countries/{id} URL, It works very good with first one, because my code is
#RequestMapping(value = {"/{id}", "/{id}/"}, method = RequestMethod.GET)
public String getCountry(#PathVariable(value = "id", required = true) int id,ModelMap model) {
}
#RequestMapping(method = RequestMethod.POST)
public String deleteCountry(ModelMap model,HttpServletRequest request) {
}
And when I try to request POST data from second url I'm getting
HTTP Status 405 - Request method 'POST' not supported
Which is expectable because I haven't POST method with this mapping, but if I will be made one method for one mapping my code will be too ugly ant terrible, what solution I can use?
Hum why not add the "array" of value to your second method as well ?
#RequestMapping(value = {"", "/{id}"},method = RequestMethod.POST)
public String deleteCountry(ModelMap model,
HttpServletRequest request) {
Btw using POST verb to call an action that looks like it will delete the resource seems wrong, it should be a DELETE verb used
EDIT
But in reality, you should be creating 2 methods, as both those method are not supposed to do the same thing.
POST /countries should be creating country resources
POST /countries/{id} should be doing something else.
For an update prefer PUT /countries/{id}
And for a delete, prefer DELETE /countries/{id}
There is one way to have separate handler interceptors for different controllers.
Refer this link for details.
bind Spring HandlerInterceptor only to one controller
But I feel, it may be good you can create a common method to share business logic for this.
As Interceptor comes with proxy class for your controller which can be avoided unless you have complex logic.

REST API endpoint selection in Spring Boot

Given a controller like this:
#RestController
#RequestMapping("/cars") {
public class CarController{
#RequestMapping(method = RequestMethod.GET)
public ResponseEntity<List<Cars>> getCars() { //logic }
#RequestMapping(method = RequestMethod.GET")
public ResponseEntity<List<Cars>> searchCar(#RequestParam("name") String name, #RequestParam("value") String value) { //logic}
}
If the url is like this localhost/cars I would like to access the getCars() method.
But if the url is :
localhost/cars?name=something&value=100 or
localhost/cars?name=something or
localhost/cars?value=100
I would like the second method to be accessed.
Is this possible to do?
You are still asking for the same list of resources, cars, only thing is that you are adding a filter or search / query criteria.
It would be beneficial to develop a query filter / criteria to support something like:
/cars?q=make+eq+acura (meaning make=acura)
/cars?q=price+lt+25000 (meaning price <25000)
and so on.
No it is not possible. because when a request comes to container then it will 1st scan all the URL and check uniqueness of the URL. If there is duplicate URL present then container will throws exception.
In your case you are using class level URL mapping, but you are not using method level URL mapping.
To access your getCars() method you need to use some URL like below
#RequestMapping(value = "/", method = RequestMethod.GET)
To access your 2nd method you need to use another mapping URL
#RequestMapping(values="/test", method = RequestMethod.GET")
You can't access
localhost/cars?name=something&value=100 or
localhost/cars?name=something or
localhost/cars?value=100
as you are using 2 parameters like #RequestParam("name") String name, #RequestParam("value") String value
you need to pass two parameter in your url like below
localhost/cars/test?name=something&value=100
if you don't want to pass any of two parameter then just pass it as null and check it inside your method

RequestMapping in spring with weird patterns

I have defined the controller method in spring like following
#RequestMapping(value = "/register", method = RequestMethod.GET)
public ModelAndView register(HttpSession session) {
and when i try to access the register page it is working fine.
localhost:8080/myapp/register
but the issue is it is giving me the same page with all these patterns
localhost:8080/myapp/register.htm
localhost:8080/myapp/register.abc
localhost:8080/myapp/register.pqrasdfdadf
i want to stop this behaviour. can anyone suggest ?
Depending on how you do your Web MVC configuration, you have to set the RequestMappingHandlerMapping useSuffixPatternMatch property to false.
If you're doing your configuration through a WebMvcConfigurationSupport sub class, simply do
#Override
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping mapping = super.requestMappingHandlerMapping();
mapping.setUseSuffixPatternMatch(false);
return mapping;
}
With XML configuration, you'll need to explicitly declare a RequestMappingHandlerMapping with id requestMappingHandlerMapping and set the corresponding <property>.
This property, which is true by default, determines
Whether to use suffix pattern match (".*") when matching patterns to
requests. If enabled a method mapped to "/users" also matches to
"/users.*".
I think if you use #RequestMapping(value = "/register/", method = RequestMethod.GET) , you can easily solve your problem.
Another Solution:
Use regular expression.
#RequestMapping(value = "{varName:/register$}")
Here $ represents the end of the string.

Mapping same URL to different controllers in spring based on query parameter

I'm using spring annotation based controller. I want my URL /user/messages to map to some controller a if query parameter tag is present otherwise to some different controller b. This is required because when parameter tag is present then some more parameters can be present along with that which i want to handle in different controller to keep the implementation clean.Is there any way to do this in spring. Also is there any other elegant solution to this problem ?
You can use the params attribute of the #RequestMapping annotation to select an controller method depending on Http parameters.
See this example:
#RequestMapping(params = "form", method = RequestMethod.GET)
public ModelAndView createForm() {
...
}
#RequestMapping(method = RequestMethod.GET)
public ModelAndView list() {
...
}
It is a REST style like Spring ROO uses: if the request contains the parameter forms then the createForm handler is used, if not the list method is used.
If you want to go the Spring route, you can checkout the HandlerInterceptor mentioned here. The Interceptor can take a look at your query param and redirect the link to something else that can be caught by another SimpleUrlMapper.
The other way is to send it to a single controller and let the controller forward to another action if the query parameter is "b".

Resources