Spring REST-ful uri with optional querystring - java

The normal uri which triggers the default controller to get all cars is just "/cars"
I want to be able to search for cars aswell with an uri, for example: "/cars?model=xyz" which would return a list of matching cars. All the request parameters should be optional.
The problem is that even with the querystring the default controller triggers anyway and I always get "all cars: ..."
Is there a way to do this with Spring without a separate search uri (like "/cars/search?..")?
code:
#Controller
#RequestMapping("/cars")
public class CarController {
#Autowired
private CarDao carDao;
#RequestMapping(method = RequestMethod.GET, value = "?")
public final #ResponseBody String find(
#RequestParam(value = "reg", required = false) String reg,
#RequestParam(value = "model", required = false) String model
)
{
Car searchForCar = new Car();
searchForCar.setModel(model);
searchForCar.setReg(reg);
return "found: " + carDao.findCar(searchForCar).toString();
}
#RequestMapping(method = RequestMethod.GET)
public final #ResponseBody String getAll() {
return "all cars: " + carDao.getAllCars().toString();
}
}

You can use
#RequestMapping(method = RequestMethod.GET, params = {/* string array of params required */})
public final #ResponseBody String find(#RequestParam(value = "reg") String reg, #RequestParam(value = "model") String model)
// logic
}
ie, the #RequestMapping annotation has a property called params. If all of the parameters that you specify are contained in your request (and all other RequestMapping requirements match), then that method will be called.

Try a variation of this:
#Controller
#RequestMapping("/cars")
public clas CarController
{
#RequestMapping(method = RequestMethod.get)
public final #ResponseBody String carsHandler(
final WebRequest webRequest)
{
String parameter = webRequest.getParameter("blammy");
if (parameter == null)
{
return getAll();
}
else
{
return findCar(webRequest);
}
}
}

Related

How to get a route

I have this controller:
#RestController("ThresholdAdapter")
#RequiredArgsConstructor
#Component
public class ThresholdAdapter {
#Autowired
ThresholdQuery thresholdQuery;
#RequestMapping(value = "/jbdj", method = RequestMethod.GET)
public String testaux() {
return "lkajdfladjlksj";
}
#RequestMapping(value = "/threshold/list", method = RequestMethod.GET)
public List<Threshold> listThreshold(#RequestParam(required = false) String categoria, #RequestParam(required = false) String kpi, #RequestParam(required = false) String data, #RequestParam(required = false) String hora) {
return thresholdQuery.listThreshold(categoria, kpi, data, hora);
}
#RequestMapping(value = "/threshold/update", method = RequestMethod.GET)
public Threshold updateThreshold(#RequestParam String kpi, #RequestParam String weekday, #RequestParam String hour, #RequestParam String valor, #RequestParam Boolean status) {
return thresholdQuery.updateThreshold(kpi,weekday,hour,valor,status);
}
}
When I call:
http://localhost:8080/jbdj
It doesn´t work.
It show the 404 Not Found error.
You need to have the annotation for rest controller for your endpoint. Spring create a bean named as "thresholdAdapter". You should not give any name in "RestController" annotation.
#RestController
#RequiredArgsConstructor
#Component("thresholdAdapter")
There was setting for context path.
Thanks a lot.

Using params in GetMapping in Spring results in ambiguous handler method for multiple parameters

I have the following REST endpoints in Spring boot
#GetMapping(value = "students", params = {"name"})
public ResponseEntity<?> getByName(#RequestParam final String name) {
return new ResponseEntity<>(true, HttpStatus.OK);
}
#GetMapping(value = "students", params = {"tag"})
public ResponseEntity<?> getByTag(#RequestParam final String tag) {
return new ResponseEntity<>(true, HttpStatus.OK);
}
The above handlers work fine for the following requests:
localhost:8080/test/students?name="Aron"
localhost:8080/test/students?tag="player"
However, whenever I try the following:
localhost:8060/test/students?name="Aron"&tag="player"
it throws java.lang.IllegalStateException: Ambiguous handler methods mapped and responds with an HTTP 500
How can I change this behavior? I want my app to respond only when I get either a tag query parameter or a name query parameter.
For anything else, I want it to ignore even if it's a combination of two parameters.
Why is it throwing the ambiguous error here and how can we handle that?
You can use #RequestParam(required = false):
#GetMapping(value = "students")
public ResponseEntity<?> get(
#RequestParam(required = false) final String name,
#RequestParam(required = false) final String tag) {
if ((name == null) == (tag == null)) {
return new ResponseEntity<>(false, HttpStatus.BAD_REQUEST);
}
return new ResponseEntity<>(true, HttpStatus.OK);
}
it seems you can use negations in params. Something like:
#GetMapping(value = "students", params = {"name", "!tag"})
public ResponseEntity<?> getByName(#RequestParam final String name) {
return new ResponseEntity<>(true, HttpStatus.OK);
}
#GetMapping(value = "students", params = {"tag", "!name"})
public ResponseEntity<?> getByTag(#RequestParam final String tag) {
return new ResponseEntity<>(true, HttpStatus.OK);
}
References: Advanced #RequestMapping options

How to add multiple RestController endpoints differed by query-params?

How can I simply redirect a url if a specific query parameter is missing?
#RestController
public class PersonController {
//only in case the "sort" query parameter is missing
#GetMapping("/persons")
public String unsorted() {
return "redirect:/persons?sort=name";
}
//only in case the "sort" query parameter exists
#GetMapping("/persons")
public String sorted() {
//...
}
}
Use #RequestParam to extract query parameters
Add parameter for #RequestParam: value, defaultValue, required
with java >= 8:
#RestController
public class PersonController {
#GetMapping("/persons")
public String personList(#RequestParam(value = "sort", defaultValue = "name") Optional<String> sort) {
//handling process here
}
}
with java < 8:
#RestController
public class PersonController {
#GetMapping("/persons")
public String personList(#RequestParam(value = "sort", defaultValue = "name", required=false) String sort) {
//handling process here
}
}
You could use #GetMapping.params
#GetMapping(value = "/persons", params = "sort")
public String sorted() {
You can use the params element. One mapping will supports params="sort" for when the sort parameter is present and the other params="!sort" for when it is missing.
However, you may want to consider using a default value instead of performing a redirect. What benefit does the redirect provide? It will require the server respond and then and have the client make a second HTTP request.
Using params
#RestController
public class PersonController {
//only in case the "sort" query parameter is missing
#GetMapping(value = "/persons", params = "!sort")
public String unsorted() {
return "redirect:/persons?sort=name";
}
//only in case the "sort" query parameter exists
#GetMapping(value = "/persons", params = "sort")
public String sorted() {
//...
}
}
Using default value
#RestController
public class PersonController {
//only in case the "sort" query parameter exists
#GetMapping("/persons")
public String sorted(
#RequestParam(name = "sort", defaultValue = "name") String sort)
{
//...
}
}
You can set a default value:
#RestController
public class PersonController {
//only in case the "sort" query parameter is missing
#GetMapping("/persons")
public String unsorted(#RequestParam(value = "sort", defaultValue = "name") String name) {
// do logic
}
}
You can also set the default value for the missing value and continue forward
#RequestParam(value = "sort", defaultValue = "name") String name

Spring - is it possible to give same url (path) in request mapping for two different post methods?

Is it possible to map same path (uri) in request mapping for two different post methods, only difference is request body.
Example
#RequestMapping(value = "/hello", method = RequestMethod.POST)
public String helloEmployee(#RequestBody Employee employee) {
return "Hello Employee";
}
#RequestMapping(value = "/hello", method = RequestMethod.POST)
public String helloStudent(#RequestBody Student student) {
return "Hello Student";
}
No, you can't give same url in request mapping of post method having different request body type but same media type. Below won't work:
#PostMapping(path = "/hello", consumes = MediaType.APPLICATION_JSON_VALUE)
public String hello(#RequestBody Pojo1 val) {
return "Hello";
}
#PostMapping(path = "/hello", consumes = MediaType.APPLICATION_JSON_VALUE)
public String hello(#RequestBody Pojo2 val) {
return "Hello";
}
If you have different media type, then it will. Below will work:
#PostMapping(path = "/hello", consumes = MediaType.APPLICATION_JSON_VALUE)
public String hello(#RequestBody Pojo val) {
return "Hello";
}
#PostMapping(path = "/hello", consumes = MediaType.TEXT_PLAIN_VALUE)
public String hello(#RequestBody String val) {
return "Hello";
}
Your RequestMapping should differ on at least one of the conditions; path,method,params,headers,consumes,produces
I needed the same url post mapping but it was giving me an error so I added different params and it worked for me
//url1 post mapping
#PostMapping(value = "/applicant/{step}", params = "validatedata")
//url2 post mapping
#PostMapping(value = "/applicant/{step}", params = "data")
if any of the below is different(as mentioned by the above answers)then you can have the same URL post mapping
path,method,params,headers,consumes,produces
In my case params was diffrent
Yes you can do that but you need to specify unique parameters signature in RequestMapping annotation:
public class MyController {
#RequestMapping(method = RequestMethod.POST, params = {"!name", "!name2"})
public String action(HttpServletRequest request, HttpServletResponse response){
// body
}
#RequestMapping(method = RequestMethod.POST, params = "name")
public String action(HttpServletRequest request, HttpServletResponse response,
#RequestParam(value = "name", required = true) String name) {
// body
}
}
`

Spring map GET request parameters to POJO automatically

I have method in my REST controller that contains a lot of parameters. For example:
#RequestMapping(value = "/getItem", method = RequestMethod.GET)
public ServiceRequest<List<SomeModel>> getClaimStatuses(
#RequestParam(value = "param1", required = true) List<String> param1,
#RequestParam(value = "param2", required = false) String param2,
#RequestParam(value = "param3", required = false) List<String> param3,
#RequestParam(value = "param4", required = false) List<String> param4,
#RequestParam(value = "param5", required = false) List<String> param5) {
// ......
}
and I would like to map all GET request parameters to a POJO object like:
public class RequestParamsModel {
public RequestParamsModel() {
}
public List<String> param1;
public String param2;
public List<String> param3;
public String param4;
public String param5;
}
I need something like we can do using #RequestBody in REST Controller.
Is it possible to do in Spring 3.x ?
Thanks!
Possible and easy, make sure that your bean has proper accessors for the fields. You can add proper validation per property, just make sure that you have the proper jars in place. In terms of code it would be something like
import javax.validation.constraints.NotNull;
public class RequestParamsModel {
public RequestParamsModel() {}
private List<String> param1;
private String param2;
private List<String> param3;
private String param4;
private String param5;
#NotNull
public List<String> getParam1() {
return param1;
}
// ...
}
The controller method would be:
import javax.validation.Valid;
#RequestMapping(value = "/getItem", method = RequestMethod.GET)
public ServiceRequest<List<SomeModel>> getClaimStatuses(#Valid RequestParamsModel model) {
// ...
}
And the request, something like:
/getItem?param1=list1,list2&param2=ok
Are you trying to do
#RequestMapping(value = "/getItem", method = RequestMethod.GET)
public ServiceRequest<List<SomeModel>> getClaimStatuses(#ModelAttribute RequestParamsModel requestParamModel) {
...
}

Categories

Resources