I am developing a Spring MVC web application. I am not still develop the UI. So I am testing my services using Advance Rest Client tool.
My Controller
#Controller
#RequestMapping("/testController")
public class TestController {
#Autowired
private TestService testService;
#RequestMapping(value = "/test", method = RequestMethod.POST, consumes = { MediaType.APPLICATION_JSON_VALUE }, produces = { MediaType.APPLICATION_JSON_VALUE })
public
#ResponseBody void testMethod(#RequestBody TestParam testParam) {
String tenant = testParam.getTenantCode();
String testString = tenant + " is the tenant";
}
}
TestParam.java class
public class TestParam {
private String testVar;
private String tenantCode;
public String getTenantCode() {
return tenantCode;
}
public void setTenantCode(String tenantCode) {
this.tenantCode = tenantCode;
}
public String getTestVar() {
return testVar;
}
public void setTestVar(String testVar) {
this.testVar = testVar;
}
}
I send the request using Advance Rest Client and headers and request link has set correctly.
{"testVar":"Test","tenantCode":"DEMO"}
Request link
http://localhost:8080/myApp/controller/testController/test
It works correctly when TestParam has one veriable. When it becomes two or more it gives an Error and it not hit the testMethod.
exception is com.fasterxml.jackson.core.JsonParseException: Unexpected end-of-input in field name at [Source:org.apache.catalina.connector.CoyoteInputStream#7b24d498; line: 1, column: 43]
at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.readJavaType(MappingJackson2HttpMessageConverter.java:181)
at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.read(MappingJackson2HttpMessageConverter.java:173)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:135)
I went throw more articles and I still couldn't find the answer.
Increasing Content-Length: in header works
Whats your json format ? I think json format uses literal \n's as delimiters, please be sure that the JSON actions and sources are not pretty printed.
There is an issue in ARC where there is no payload and the response is of a type of json. Parser is throwing error because the string is empty and the response report is crashing.
Related
I am building and testing a simple Spring Boot API REST tutorial.
I have faced with an issue that I am trying to understand. I am getting an HTTP 406 (NOT ACCEPTABLE) when calling POST method to create and persist a new entity.
Problem is the entity is persisted but the response to the client is not what should be expected (HTTP 201 CREATED with URI in this case).
Tutorial and TutorialDto classes have the exact same attributes. Here is the definition:
public class TutorialDto {
private long id;
private String title;
private String description;
private boolean published;
...
}
Here is my POST method in #RestController class:
#PostMapping("/tutorial")
public ResponseEntity.BodyBuilder createTutorial(#RequestBody final TutorialDto tutorialDto) {
final TutorialDto createdTutorial = tutorialService.add(tutorialDto);
return ResponseEntity.created(URI.create(String.format("tutorial/%d", createdTutorial.getId())));
}
And here is the #Service method to create the entity:
#Transactional
public TutorialDto add(final TutorialDto tutorialDto) {
final Tutorial createdTutorial = tutorialRepository.save(modelmapper.map(tutorialDto, Tutorial.class));
return Optional.of(modelmapper.map(createdTutorial, TutorialDto.class))
.orElseThrow(() -> new TutorialCreationException(
String.format("Tutorial: %s could not be created", tutorialDto.getTitle()))
);
}
This is the request body:
{
"title": "tutorial",
"description": "This is the first created tutorial"
}
And this is the response body:
{
"timestamp": "2022-04-16T00:40:36.626+00:00",
"status": 406,
"error": "Not Acceptable",
"path": "/api/v1/tutorial"
}
I am getting the HTTP 406 response at the end of the controller method, after returning the "ResponseEntity.created".
Thanks in advance.
Looks like you are using wrong usage of ResponseEntity.BodyBuilder. Here is an example
Hence, your controller code should look something like this:
#PostMapping("/tutorial")
public ResponseEntity createTutorial(#RequestBody final TutorialDto tutorialDto) {
final TutorialDto createdTutorial = tutorialService.add(tutorialDto);
return ResponseEntity.created(URI.create(String.format("tutorial/%d", createdTutorial.getId()))).body(createdTutorial);
}
I am trying to make a post request using json but in postman the request is successful only if I make the request like this: email#example.com. If I make a request using the standard JSON format {"email":"email#example.com"} I get "invalid email id". I should mention that content type application/json header is checked in postman, and I am making the request in body/raw.
I have tried messing with #RequestBody/#RequestParam annotations, using consumes = "application/json" but I am unsuccessful and I couldn't find a similar issue after lots of googling either.
my controller:
#RestController
public class UserController {
#Autowired
private UserService userService;
#PostMapping(value = "/forgot-password", consumes = "application/json")
public String forgotPassword(#RequestBody String email) {
String response = userService.forgotPassword(email);
if (!response.startsWith("Invalid")) {
response = "http://localhost:8080/reset-password?token=" + response;
}
return response;
}
user service:
public String forgotPassword(String email) {
Optional<User> userOptional = Optional
.ofNullable(userRepository.findByEmail(email));
if (!userOptional.isPresent()) {
return "Invalid email id.";
}
User user = userOptional.get();
user.setToken(generateToken());
user.setTokenCreationDate(LocalDateTime.now());
user = userRepository.save(user);
return user.getToken();
}
Simply put, the #RequestBody annotation maps the HttpRequest body to a transfer or domain object.You need to put object instead of String
Your endpoint should be like Below.
#PostMapping(value = "/forgot-password", consumes = "application/json")
public String forgotPassword(#RequestBody EmailDto email) {
String response = userService.forgotPassword(email.getEmail);
// ...
return response;
}
Your DTO should be like below
public class EmailDto {
private String email;
//Getters and Setters
}
You should have Email model with string property email.
public EmailPayload {
String email;
.....
Then it will work (it will fit json you provided).
Ofcouse class name can be different, only thing that must match is email property, then in your Controller your #RequestBody will be this class, and not String you have now.
I am making a simple API using Spring. and i am getting this error while uploading and mapping file.
The server refused this request because the request entity is in a format not supported by the requested resource for the requested method.
this is my Controller ->
#RequestMapping(value = "/Hi", method = RequestMethod.POST, produces = { "application/json" })
#ResponseBody
public BasicResponse UploadData(#RequestBody CropImageData cropImageData, HttpServletRequest request) {
BasicResponse basicResponse = new BasicResponse();
System.out.println(cropImageData.getCropId());
return basicResponse;
}
My cropImageData model class ->
public class CropImageData {
#JsonProperty("cropImages")
private MultipartFile[] cropImages;
#JsonProperty("cropId")
private String cropId;
public MultipartFile[] getCropImages() {
return cropImages;
}
public void setCropImages(MultipartFile[] cropImages) {
this.cropImages = cropImages;
}
public String getCropId() {
return cropId;
}
public void setCropId(String cropId) {
this.cropId = cropId;
}
}
this is how i am sending request via POSTMAN.
With Postman, you are sending a HTTP post form-data but your end point is not configured to receive this format (the consumes = { "multipart/form-data" } annotation is missing).
Instead of your model class, you should change the signature of your method to something like that:
public BasicResponse UploadData(#RequestPart("cropId") String cropId, #RequestPart("cropImages") MultipartFile file)
I´m having some issues when returning some errors from a rest WebService.
Making a request with the header {"Accept":"application/octet-stream"}
(the service returns a document ResponseEntity<InputStreamResource> if all the process goes well).
When all the process goes well the document is downloaded fine, but when an error is occurred and the code jumps to the #ControllerAdvice and tries to return a JSON error. Here comes the problem, when trying to return the JSON springs crashes:
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
Here is a example of some code:
Controller
#RequestMapping(value = "/test", method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_OCTET_STREAM_VALUE })
public ResponseEntity<CustomError> test() throws Exception {
throw new Exception();
}
ControllerAdvice
#ControllerAdvice
public class ExceptionHandlerAdvice {
private static final Logger logger = LogManager.getLogger(ExceptionHandlerAdvice.class);
#ExceptionHandler({Exception.class,Throwable.class})
#ResponseBody
public ResponseEntity<CustomError> handleUnhandledException(Exception exception) {
CustomError error = new CustomError(exception.getMessage());
return new ResponseEntity<CustomError>(error, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
CustomError:
public class CustomError {
private String errorDescription;
public CustomError(String errorDescription) {
super();
this.errorDescription = errorDescription;
}
public String getErrorDescription() {
return errorDescription;
}
public void setErrorDescription(String errorDescription) {
this.errorDescription = errorDescription;
}
}
I´ve also tried returning new headers on #controllerAdvice
#ExceptionHandler({Exception.class,Throwable.class})
#ResponseBody
public ResponseEntity<CustomError> handleUnhandledException(Exception exception) {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
CustomError error = new CustomError(exception.getMessage());
return new ResponseEntity<CustomError>(error,headers, HttpStatus.INTERNAL_SERVER_ERROR);
}
Any idea how can I make this work or ignore Accept header on response?
It´s possible?
Thanks in advance
This exception means your response type not match with your request header. If you are expecting JSON/Stream to be returned, your request header should be {"Accept":"application/octet-stream,application/json"}.
Spring throws an error when I send json array. I am not sure what I am missing here.
RequestBody
{
"deliverySessionId":"c1fb327b-98a8-46d4-9e82-ce7507b5be93",
imageNames: ["name1", "name2"]
}
Endpoint
#RequestMapping(value = { "/examImages/" }, method = { RequestMethod.POST } )
public #ResponseBody ImageResponseCommand streamExamImages( #RequestBody ImageResponseCommand imageResponseCommand ) {
Error
The request sent by the client was syntactically incorrect.
It works fine if my request doesn't contain imageNames property.
{ "deliverySessionId":"c1fb327b-98a8-46d4-9e82-ce7507b5be93" }
Your JSON string isn't formatted properly. Object key's need to be wrapped in quotes.
{
"deliverySessionId":"c1fb327b-98a8-46d4-9e82-ce7507b5be93",
"imageNames": ["name1", "name2"]
}