ServletRequestParameter exception, parameter is not present - spring-boot

I am creating an API, using Spring Boot and using PostMan to debug and test the system. Now I am having a difficulty in sending a class object as a parameter.
I wish to send an Entity passed as a parameter and display whether the entity has a specified certification or not.
Currently I am using Postman and using the raw "JSON" format to display my Entity Object, however I am getting an error
"resolved [org.springframework.web.bind.MissingServletRequestParameterException: Required Entity parameter 'store' is not present]"
Can anyone point me in the direction of what the problem could be
My JSON (this is the Entity CLass Object that I created, I am not able to recieve a response from the API, the API should send the string "Passed Check"
{
"id": 1,
"name": "asdasd",
"phoneNumber": "000",
"address": "asdasdasdasdasd",
"latitude": 0.0,
"longitude": 0.0,
"dateAdded": "06/08/2020"
}
Certification Controller
#Controller
public class CertController {
#Autowired
private CertificationRepository certRepo;
#Autowired
private StoreRepository StoreRepository;
#GetMapping(value = "/getCertification")
#GetMapping(value = "/getCertObject")
public #ResponseBody
String getCertificationPOJO(#RequestParam Entity store)
{
return "Passed check";
}
}
Postman Error

In the code you shared, I see a few issues.
Missing Path to Controller
Add #RequestMapping("/cert") on CertController.
#Controller
#RequestMapping("/cert")
public class CertController {
}
Wrong Parameter Type
getCertificationPOJO method should have #RequestBody instead of #RequestParam annotation
#GetMapping(value = "/getCertObject")
public #ResponseBody String getCertificationPOJO(#RequestBody Entity store) {
return "Passed check";
}
You can easily follow this guide: Building a RESTful Web Service

Related

How do I create a Spring Boot endpoint that can accept multiple different types as RequestBody?

I have 2 messages like this...
{
"type":"MessageString",
"message": {
"value":"..."
}
}
and
{
"type":"MessageObject",
"message": {
"value": { ... }
}
}
Then I have a Spring Boot endpoint like...
#Controller
#RequestMapping("...")
public class MyController {
#PostMapping(
consumes = MediaType.APPLICATION_JSON_VALUE
)
#ResponseBody
public String processMessage(
#RequestBody (?) wrapper
){
...
}
}
I would like to know what kind of classes I can use to accept both types? I had it working like this....
class MessageWrapper<T extends MessageType>{
private T message;
}
But then I still have to declare the type in the response body like...
#RequestBody MessageWrapper<Object> wrapper
or
#RequestBody MessageWrapper<String> wrapper
So this wouldn't work because I can't have 2 response bodies.
I am trying to keep this as simple as possible so I would like to avoid making the #RequestBody a string then parsing it inside the controller.

ResponseEntity<MyDTO> is Returning Missing/Incomplete JSON

I'm seeing an issue with JSON cut-off/missing/incomplete when getting a response back from my service in Spring Boot.
Example:
ResponseEntity<MyDTO> responseEntity = myService.getMyDTO();
return responseEntity;
public class MyService {
public ResponseEntity<MyDTO> getMyDTO() {
return restTemplate.exchange(requestUrl, HttpMethod.GET, new HttpEntity<>(httpHeaders), MyDTO.class)
}
}
When debugging and inspecting the body of ResponseEntity, which is MyDTO instance, it contains
all the expected fields.
public class MyDTO {
private Information information;
private Address address;
}
public class Information {
private String firstName;
private String lastName;
}
public class Address {
private String streetName;
}
Debugging:
MyDTO
body
information
firstName > "John"
lastName > "Doe"
address > null
Expected JSON:
{
"information": {
"firstName": "John",
"lastName": "Doe"
},
"address: null
}
Actual JSON:
{
"information": {
"firstName": "Jo
Yes, the ending brackets are even missing from the response JSON.
Note: address is null because the response from upstream service returns a 400 and we map that response to our DTO (MyDTO). Initially, I thought this was the problem until debugging confirmed that the mapping was done correctly.
Here's what's really strange. If I take that ResponseEntity's body and put it in another ResponseEntity, than it returns fine and works. The service even returns faster, which is weird too.
ResponseEntity responseEntity = myService.getMyDTO();
return new ResponseEntity(responseEntity.getBody(), responseEntity.getStatusCode());
Anyone knows what's going on? Is it a networking, Spring Boot, or my code issue? Why would returning a new ResponseEntity fix the issue?
Found the issue. The upstream service contains a 'Content-Length' header, which is too small and causing the missing/incomplete JSON on client-side.
This is happening because you are calling the restTemplate.exchange() method; if you use the getForObject() method (in case of post call postForObject()) instead it will work.
This method will first create the MyDTO class object and then you need to add that object in the ResponseEntity object to return it.
Example:
MyDTO myDtoObject = restTemplate.getForObject(requestUrl, MyDTO.class);
return new ResponseEntity<>(myDtoObject, HttpStatus.OK);

Spring Data Rest, SpringFox and JpaRepository custom finders

NB: using Spring Boot 1.4.2 + SpringFox 2.6.0
Hi, I'm having an issue with Swagger 2 forms on my API documentation over a #RepositoryRestResource. The code below works fine (REST access OK):
#RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends JpaRepository<Person, Long> {
Person findByLastName(#Param("name") String name);
}
And the HATEOAS links are right too: calling URL /api/people/search
ends up with this (notice parameter "name"):
{
"_links": {
"findByLastName": {
"href": "http://localhost:8080/api/people/search/findByLastName{?name}",
"templated": true
},
"self": {
"href": "http://localhost:8080/api/people/search"
}
}
}
The REST API is ok: URL /api/people/search/findByLastName?name=foobar returns data when executed with a browser
BUT in Swagger the GET parameter type is interpreted as "body" instead of "query" and the form submission (curl ... -d 'foobar'...) fails in 404, attempting to submit "name" as request body.
So I tried to set Swagger explicitly, like this:
#RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends JpaRepository<Person, Long> {
#ApiOperation("Find somebody by it's last name")
#ApiImplicitParams({
#ApiImplicitParam(name = "name", paramType = "query")
})
Person findByLastName(#Param("name") #ApiParam(name = "name") String name);
}
without any success, despite the fact that "name" is well retained in the form as the parameter name in this example :-(
body parameter type on GET query
Does anyone know what could be done to make that Swagger form to work? Thx for your help
This is it : #Param configures Spring Data REST, while #RequestParam fits Swagger
#RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends JpaRepository<Person, Long> {
// #Param Spring Data REST : Use #Param or compile with -parameters on JDK 8
// #RequestParam Swagger : paramType=query cf. $Api*Param
Person findByLastName(#Param("name") #RequestParam("name") String name);
}
Me happy!

Spring MVC REST - standard request body wrapper

What is the best way to achieve a common REST request body unwrap effect with Spring MVC #RestController ?
In other words, assuming I have the following controller:
#RestController
public class MyController {
#RequestMapping(value = "/", method = POST)
public Object hello(#RequestBody MyDTO dto) {
...
}
}
I would like the actual post body to be:
{
"version": "1.0",
"payload": {
...
}
}
Which can be represented by the following class:
public class ApiRequestDTO<TPayload> {
private String version;
private TPayload payload;
...
// Getters and Setters...
...
}
So in this particular case the client would send an instance of ApiRequestDTO<MyDTO>.
I achieved the opposite (response body wrapper) using a #ControllerAdvice, but I notice that it won't work exactly for the request body. One possible approach I can see is to decorate all the relevant message converters. But I was wondering if there is a better approach?

how to bind different POST objects with one request mapping in Spring?

Here is how my url looks like
http://localhost/controller/check
Here is the requestmapping
#RequestMapping(method = RequestMethod.POST)
public Data check(#RequestBody final Check checkRequest, final HttpServletResponse servletResponse) {
// service layer
}
Now I want the Check object to handle both the following POJOS.
public class Check {
String name;
String email;
}
public class Check {
int age;
Location location;
}
The request mapping should handle the following POST body.
{"age" : 23, "location" :{ "region": XXX, "country":"xxx", "zipcode":xxx}
and
{"name": "yyyy", "email":"hello#bar.com"}
what is the recommended approach here?
If it makes sense just combine the attributes into just 1 class. The json mapping will work with the missing atributes will be mapped to null.
If you still need 2 different models create a wrapper called CheckRequest which has 2 memeber variables checkName & checkLocation and post the appropriate json
I will extend the Check class and will put the newly extended class in the request body.

Resources