Getting null with #pathparam and #requestmapping - spring-boot

I am using spring-boot 1.4.3.RELEASE for creating web services, whereas, while giving the request with http://localhost:7211/person/get/ram, I am getting null for the id property
#RequestMapping(value="/person/get/{id}", method=RequestMethod.GET, produces="application/json")
public #ResponseBody Person getPersonById(#PathParam("id") String id) {
return personService.getPersonById(id);
}
Can you please suggest me, is there anything I missed.

The annotation to get path variable is #PathVariable. It looks like you have used #PathParam instead which is incorrect.
Check this out for more details:
requestparam-vs-pathvariable

As above answers already mentioned #PathVariable should be used, I thought to clear the confusion between #PathVariable & #PathParam.
Most people get confused on this part because Spring and other rest implementation like Jersey use sightly different annotations for the same thing.
#QueryParam in Jersey is #RequestParam in Spring Rest API.
#PathParam in Jersey is #PathVariable in Spring Rest API.

Use #PathVariable annotation instead of #PathParam.

id should be Long instead of String at #PathVariable. If so, then ...
#RequestMapping(value="/person/get/{id}", method=RequestMethod.GET, produces="application/json")
public #ResponseBody Person getPersonById(#PathVariable("id") Long id) {
return personService.getPersonById(id);
}

Related

How to capture a common request parameter for all requests in spring BOOT REST

In Jersey Rest API
if any common request parameters are there then we can capture that value at RootResource level using the below code.
#QueryParam("q")
private String qQueryParams
Is there any similar approach in Spring Rest API.
In other words, all my endpoint URL will contain the query parameter "q". How to capture this data at class level instead of every request.
Thanks, Vijay
you can use #RequestMapping({q}/test) above controller and pass #PathVariable String q as method argument.
#Controller
#RequestMapping(value = "{q}/test")
class TestController {
#RequestMapping(value="/abc")
public ModelAndView doSomething(#PathVariable String q) {
// do something with q...
}
}

Spring RESTful application - POST method request body mandatory attributes

I am building a RESTful app in Spring Boot and i want to make few attributes in my POST method's request body mandatory.
In swagger yaml, i mark them as required "true", but when i generate the classes using swagger editor, i dont see that impacting in any way, i.e i can't see even a #NotNull annotation or anything of that sort.
How do i mark them as mandatory in my java model class ? Is #NotNull the way to go?
If yes, should i do that in my request body class, or in the jpa document class or both ?
Thanks !
Yes, #NotNull is a way to go.
But also You need to use #Valid annotation.
check example:
#RequestMapping(value = "/appointments", method = RequestMethod.POST)
public String add(#Valid AppointmentForm form, BindingResult result) {
....
}
static class AppointmentForm {
#NotNull
private Date date;
}

What's the reason to use ResponseEntity<?> return type instead of simple ResponseEntity in Spring Controller?

I've seen a lot of examples of Spring Controllers implementation that use ResponseEntity<?> in order to return HTTP response that have a specific status code and optional body.
ResponseEntity<?> notation is present even in official Spring tutorials like the following one: Building REST services with Spring
What's the reason to use ResponseEntity<?> instead of simple ResponseEntity?
It's a little bit related to my previous question: SonarQube complains about using ResponseEntity with a wildcard
There is some explanation in What is a raw type and why shouldn't we use it? thread, but I'd like to pay more attention to ResponseEntity class and it's use in Spring Controllers.
Consider the following snippet of code where somethingService returns an Optional of Something class:
#GetMapping
ResponseEntity<?> getSomething() {
return somethingService.getSomething()
.map(smth -> new ResponseEntity<>(smth, HttpStatus.OK))
.orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
Is there any reason to leave a wildcard even if I don't get any profit from compiler checks since ResponseEntity(HttpStatus status) parametrises ResponseEntity with Object class?

Feign Client with Spring Boot: RequestParam.value() was empty on parameter 0

I created a simple Feign Client with Spring Boot like this:
#FeignClient("spring-cloud-eureka-client")
public interface GreetingClient {
#RequestMapping("/greeting")
String greeting(#RequestParam String name);
}
But when I try just to start an application I get an error:
java.lang.IllegalStateException: RequestParam.value() was empty on parameter 0
First I didn't understand what is the reason and googled a lot but didn't find an answer. Almost excidentely I figured out that it works if to write request param name explicitly:
#RequestParam("name") String name
So my question: is it a bug or could it be configured to not write request params names explicitly?
Both Spring MVC and Spring cloud feign are using the same ParameterNameDiscoverer - named DefaultParameterNameDiscoverer to find parameter name. It tries to find the parameter names with the following step.
First, it uses StandardReflectionParameterNameDiscoverer. It tries to find the variable name with reflection. It is only possible when your classes are compiled with -parameters.
Second, if it fails, it uses LocalVariableTableParameterNameDiscoverer. It tries to find the variable name from the debugging info in the class file with ASM libraries.
The difference between Spring MVC and Feign occurs here. Feign uses above annotations (like #RequestParam) on methods of Java interfaces. But, we use these on methods of Java classes when using Spring MVC. Unfortunately, javac compiler omits the debug information of parameter name from class file for java interfaces. That's why feign fails to find parameter name without -parameter.
Namely, if you compile your code with -parameters, both Spring MVC and Feign will succeed to acquire parameter names. But if you compile without -parameters, only Spring MVC will succeed.
As a result, it's not a bug. it's a limitation of Feign at this moment as I think.
Just use String greeting(#RequestParam("name") String name);
#FeignClient("spring-cloud-eureka-client")
public interface GreetingClient {
#RequestMapping("/greeting")
String greeting(#RequestParam("name") String name);
}
I use upgrade maven-compiler-plugin to solve this plobrem. you can access: https://blog.51cto.com/thinklili/2566864
This worked for me.
#FeignClient(name="session-service", url="${session.host}")
public interface SrocessingProxy {
#RequestMapping(value = "/process/{key}", method = RequestMethod.POST)
public Response processSession(#RequestParam String key, #RequestBody PayloadHolder payload);
}
//Service
#RequestMapping(value = "/process/{key}", method = RequestMethod.POST)
public Response processSession(#RequestParam String key, #RequestBody PayloadHolder payload) {
System.out.print("Key : " + key);
}

Spring RestController url for findById and findByIds

In my Spring Boot application I have a following REST controller:
#RestController
#RequestMapping("/v1.0/decisions")
public class CriterionController {
#Autowired
private CriterionService criterionService;
#RequestMapping(value = "/{decisionId}/criteria/{criterionId}", method = RequestMethod.GET)
public CriterionResponse findById(#PathVariable #NotNull #DecimalMin("0") Long decisionId, #PathVariable #NotNull #DecimalMin("0") Long criterionId) {
Criterion criterion = criterionService.findById(criterionId);
return new CriterionResponse(criterion);
}
}
Everything is working fine and I'm able to retrieve Criterion by its ID.
Right now I need to add additional logic to my CriterionController that will retrieve Criterion by a set of IDs.
Right now I'm in doubt how it can be implemented.. For example should I add a separated endpoint something like:
/{decisionId}/criteria/{criterionIds}
or for example reuse existing one for this purpose or in some other way. Please advise how to implement it according to a best practice of REST.
This is a tricky question, but there are 2 options I can suggest:
/{decisionId}/criteria?id=1&id=2&id=3
or
/{decisionId}/criteria?id=1,2,3
The former could be seen as more RESTful but can end up with a very long URL since you'll be specifying the query parameter each time.
The latter aggregates the ids in a comma separated list. I personally prefer this option and would go for this.
Although not about REST, both URLs are accepted in Section 3.2.8 of RFC 6570

Resources