I have the following code:
#PostMapping()
public ResponseEntity<Object> postAccounts(
#RequestHeader(value = "client-id", required = true) String clientId,
#RequestHeader(value = "X-client-Global-Id", required = false) String clientGlobalID,
#RequestHeader(value = "Authorization", required = true) String authorization,
#Valid #RequestBody(required = true) String inputContract, #RequestBody(required = true)String nameInput, #RequestBody(required = true) Boolean state) {
return new ResponseEntity<>(inputContract, HttpStatus.OK);
}
When call this method by postman give me an error.
trace": "org.springframework.http.converter.HttpMessageNotReadableException: I/O error while reading input message; nested exception is java.io.IOException: Stream closed\r\n\tat org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:217)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:158)\r\n\tat
You only can send an one RequestBody, if you want send more than one properties in the body. You must create an object
#PostMapping()
public ResponseEntity<Object> postAccounts(
//Other Headers...,
#Valid #RequestBody(required = true) ObjectWithAllFields) {
return new ResponseEntity<>(ObjectWithAllFields, HttpStatus.OK);
}
EDIT 1
And pls send your error trace.
Related
I am generating the swagger docs for my REST API using SpringFox.
I have added an optional parameter to my API now:
#ApiOperation(
value = "Get all cars"
)
#GetMapping(value = "/cars", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ResponseDTO<CarDTO>> getCars(
#RequestParam(defaultValue = "1") Integer page,
#RequestParam(required = false) String status) {
ResponseDTO<CarDTO> response = service.getCars(page, status);
return ResponseEntity.ok(response);
}
How do I highlight in the swagger docs that one is required and the other is optional?
You have the #ApiParam annotation you can use, it has a property required which you can put to true or false depending on your needs
#ApiOperation(
value = "Get all cars"
)
#GetMapping(value = "/cars", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ResponseDTO<CarDTO>> getCars(
#ApiParam(required = true) #RequestParam(defaultValue = "1") Integer page,
#ApiParam(required = false) #RequestParam(required = false) String status) {
ResponseDTO<CarDTO> response = service.getCars(page, status);
return ResponseEntity.ok(response);
}
As you can see in the documentation, it has other properties like
access
allowableValues
allowMultiple
defaultValue
name
value
I need to send a value from an Angularjs front to a springboot Java back-office.
The back is called by many other fronts and services.
Which means I can change The front but I have to make sure that any change on the back must not break it for the other callers.
So Extra headers or Other fields in the request body etc... any change that won't break the other existing calls is what I'm looking for.
An example of some methods signature:
A HTTP GET signature
#Override
#ResponseStatus(code = HttpStatus.OK)
#RequestMapping(value = "/", method = RequestMethod.GET)
public ResponseEntity<List<Something>> getSomething(
#RequestHeader(name = Constants.HEADER.SOME_CODE) final String code,
#RequestHeader(name = Constants.HEADER.COMPANY_ID) final String companyId,
#RequestHeader(name = Constants.HEADER.CLIENT_ID) final String clientId) {
A HTTP POST signature
#Override
#ResponseStatus(code = HttpStatus.OK)
#RequestMapping(value = "/{pathValue}/transactions", method = RequestMethod.POST)
public ResponseEntity<SomeResponse> requestSomething(
#RequestHeader(name = Constants.HEADER.EFS_CODE) final String vode,
#RequestHeader(name = Constants.HEADER.COMPANY_ID) final String companyId,
#RequestHeader(name = "Access-Code", required = false) final String codeAcces,
#RequestHeader(name = Constants.HEADER.CLIENT_ID) final String clientId,
#PathVariable("pathValue") final String pathValue,
#RequestBody #Valid Transact transaction) {
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
I'm new in Spring Boot and I want to have the same Request Mapping method for JSON and simple request params, for example:
#RequestMapping(value = "/start")
public String startPostProcess(#RequestParam(value = "url",
required = false,
defaultValue = "https://goo.gl") String url,
#RequestParam(value = "word",
required = false,
defaultValue = "Search") String word,
#RequestBody String hereGoesJSON) {
//Do some stuff
}
So, when request goes with params, only #RequestParam will work, in other cases we will use #RequestBody annotation.
localhost:8080/start?url=htts://google.com&word=Luck
Or may bee I'll be able to write method like this, for accepting any params:
#RequestMapping(value = "/start")
public String startPostProcess(#RequestBody String anyParam) {
//Parse this anyParam
}
?
I've not found this trick in spring documentation, so I will appreciate any links to it.
Okay, I've solved the problem :D
All that I just needed was 2 methods with the same mapping and explicitly specify RequestMethod type:
#RequestMapping(value = "/start")
public String startPostProcess(#RequestParam(value = "url",
required = false,
defaultValue = "https://goo.gl") String url,
#RequestParam(value = "word",
required = false,
defaultValue = "Search") String word) throws InterruptedException {
//Do some stuff
}
#RequestMapping(value = "/start", method = RequestMethod.POST, consumes = "application/json")
public String startJsonProcess(#RequestBody String body) {
//Do another stuff with RequestBody
}
UPD: added "consumes = "application/json". It helps dividing simple POST requests and JSON POST requests.
I have been trying to create a small java client to call Highchart Export server to get the pdf/jpeg etc.. but it is not successful using Spring's RestTemplate -> RestTemplate restTemplate = new org.springframework.web.client.RestTemplate() in the client side. I tried post/get/exchange methods.. but unable to PASS the required method parameters to the server side... the required method is getting called without the params and returnd their test jsp page.
Highchart Export Server code =>
#Controller
#RequestMapping("/")
public class ExportController extends HttpServlet {
...
...
#RequestMapping(method = {RequestMethod.POST, RequestMethod.GET})
public HttpEntity<byte[]> exporter(
#RequestParam(value = "svg", required = false) String svg,
#RequestParam(value = "type", required = false) String type,
#RequestParam(value = "filename", required = false) String filename,
#RequestParam(value = "width", required = false) String width,
#RequestParam(value = "scale", required = false) String scale,
#RequestParam(value = "options", required = false) String options,
#RequestParam(value = "globaloptions", required = false) String globalOptions,
#RequestParam(value = "constr", required = false) String constructor,
#RequestParam(value = "callback", required = false) String callback,
#RequestParam(value = "callbackHC", required = false) String callbackHC,
#RequestParam(value = "async", required = false, defaultValue = "false") Boolean async,
#RequestParam(value = "jsonp", required = false, defaultValue = "false") Boolean jsonp,
HttpServletRequest request,
HttpSession session) throws ServletException, InterruptedException, SVGConverterException, NoSuchElementException, PoolException, TimeoutException, IOException, ZeroRequestParameterException {
...
}
}
What method in RestTemplate should I call and how to pass the params from client side like JSON formatted options, type etc, so that above Service method gets executed with proper params? Your help is appreciated.
I made it work after passing values in org.springframework.util.LinkedMultiValueMap object like
MultiValueMap<String, String> prms = new LinkedMultiValueMap<String, String>();
prms.add("param1", "value1");
prms.add("param2", "value2");
and then calling..
RestTemplate restTemplate = new RestTemplate();
byte[] b = restTemplate.postForObject("http://****/", prms, byte[].class);