Code is
#RestController
#Component
#Slf4j
public class ServicesController {
#CrossOrigin
#PutMapping(
consumes = "multipart/form-data",
path = "/{id}/{route}/structure_article/{filename:.+}")
public ResponseEntity<ServiceResponse> updateStructureXMLFile(
#PathVariable("id") final String id,
#PathVariable("route") final String route,
#RequestParam("file") final MultipartFile uploadfile,
#PathVariable("filename") final String fileName) throws IOException {
(Some processing)
return new ResponseEntity<>(response, httpHeaders, HttpStatus.CREATED);
}
}
Here response is a POJO with public getters and setters.
enter image description here
When I am putting a file getting this error:
{
"timestamp": 1596783608973,
"status": 406,
"error": "Not Acceptable",
"exception": "org.springframework.web.HttpMediaTypeNotAcceptableException",
"message": "Could not find acceptable representation",
"path": "/7f3033d7-3979-45e0-9f0a-172b60568edb/articles/structure_article/manuscript.xml"
}
What can be solution for this?
Thank you
In my case, the Content Negotiation was configured like:
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer
.favorPathExtension(true)
.defaultContentType(MediaType.APPLICATION_JSON)
.mediaType("xml", MediaType.APPLICATION_XML)
.mediaType("json", MediaType.APPLICATION_JSON);
}
and just like you, I have a controller method with
#PutMapping("/user/{userId:.+}")
So, Spring tries to treat a request /user/email#domain.com for example with the Content-Type of .com file extension which does not exist in the Common MIME types, hence the 406 error.
I resolved it by turning off favorPathExtension.
Related
So I have this API:
public Map<String, Object> myFunc(#RequestBody #Valid MyPrivateEntity body) {}
Which is marked with #RequestBody and #Valid
The thing is, if I omit the body when calling this API, I get the following error message:
{
"title": "Failed to parse request",
"detail": "Required request body is missing: public com.privatePackage.misc.service.rest.MyPrivateEntity com.privatePackage.misc.service.rest.MyPrivateResource.myFunc(java.lang.String, com.privatePackage.misc.service.rest.MyPrivateEntity)",
"status": 400
}
I don't want the error message to include class names and paths, instead just "Required request body is missing".
How can I do that?
Thanks
Try this code
#ExceptionHandler(BindException.class)
#ResponseStatus(HttpStatus.BAD_REQUEST) // return 400 if validate fail
public String handleBindException(BindException e) {
// return message of first error
String errorMessage = "Request not found";
if (e.getBindingResult().hasErrors())
e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
return errorMessage;
}
Or use this way
public Map<String, Object> myFunc(
#RequestBody #Valid MyPrivateEntity body,
BindingResult bindingResult) { // add this parameter
// When there is a BindingResult, the error is temporarily ignored for manual handling
// If there is an error, block it
if (bindingResult.hasErrors())
throw new Exception("...");
}
Reference:
https://www.baeldung.com/spring-boot-bean-validation
If you need more control on only this endpoint then I'll suggest to mark request body optional and check in the method if it's null then return whatever message you want to show.
#RequestBody(required = false)
Try #ControllerAdvice to customise your message.
#ControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {
#Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(
HttpMessageNotReadableException ex, HttpHeaders headers,
HttpStatus status, WebRequest request) {
// paste custom hadling here
}
}
Reference:
https://ittutorialpoint.com/spring-rest-handling-empty-request-body-400-bad-request/
I am making a simple rest service that makes some http calls and aggregates data using RestTemplate.
Sometimes i get NotFound error and sometimes BadRequest errors.
I want to respond with the same status code to my client and Spring seems to have this mapping out of the box. the message is okay but the Status code is always 500 Internal Server error.
I Would like to map my status code to the one i am initially receiving
"timestamp": "2019-07-01T17:56:04.539+0000",
"status": 500,
"error": "Internal Server Error",
"message": "400 Bad Request",
"path": "/8b8a38a9-a290-4560-84f6-3d4466e8d7901"
}
i would like it to be this way
"timestamp": "2019-07-01T17:56:04.539+0000",
"status": 400,
"error": "Internal Server Error",
"message": "400 Bad Request",
"path": "/8b8a38a9-a290-4560-84f6-3d4466e8d7901"
}
It throws HttpClientErrorException.BadRequest or HttpClientErrorException.NotFound
my code is a simple endpoint :
#GetMapping("/{id}")
public MyModel getInfo(#PathVariable String id){
return MyService.getInfo(id);
}
You can create global exception handling with #ControllerAdvice annotation. Like this:
#ControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
#ExceptionHandler(value = YourExceptionTypes.class)
protected ResponseEntity<Object> handleBusinessException(RuntimeException exception, WebRequest request) {
return handleExceptionInternal(exception, exception.getMessage(), new HttpHeaders(), HttpStatus.NOT_ACCEPTABLE, request);
}
}
When an exception is thrown, the handler will catch and transform it to the desired response. The original exception wont be propagated.
The accepted solution with the #ControllerAdvice is insufficient. That surely marks the response with the custom status code for the exception. It does, however, not return the wanted response body as JSON but as only simple string - the message from the exception.
To get the correct status code and the default error body the DefaultErrorAttributes can help.
#ControllerAdvice
public class PackedTemplateNotRecodableExceptionControllerAdvice extends ResponseEntityExceptionHandler {
#Autowired
private DefaultErrorAttributes defaultErrorAttributes;
#ExceptionHandler(PackedTemplateNotRecodableException.class)
public ResponseEntity<Object> handlePackedTemplateNotRecodableException(final RuntimeException exception, final WebRequest webRequest) {
// build the default error response
webRequest.setAttribute(RequestDispatcher.ERROR_STATUS_CODE, HttpStatus.BAD_REQUEST.value(), RequestAttributes.SCOPE_REQUEST);
final Map<String, Object> errorAttributes = defaultErrorAttributes.getErrorAttributes(webRequest, ErrorAttributeOptions.defaults());
// return the error response with the specific response code
return handleExceptionInternal(exception, errorAttributes, new HttpHeaders(), HttpStatus.BAD_REQUEST, webRequest);
}
}
That way you'll receive the wanted error response, e.g. something like this:
{
"timestamp": "2019-07-01T17:56:04.539+0000",
"status": 400,
"error": "Internal Server Error",
"message": "400 Bad Request",
"path": "/8b8a38a9-a290-4560-84f6-3d4466e8d7901"
}
I have spent a lot of time looking into this issue, including solutions from answers here, which didn't work for me (or I didn't implement correctly).
I finally got a breakthrough. Instead of throwing a generic Exception such as throw new Exception(message), I created classes that extends the Exception class for the specific exception type - with their respective HTTP error codes and message
#ResponseStatus(value = HttpStatus.BAD_REQUEST)
public class BadRequestException extends Exception{
public BadRequestException(String message) {
super(message);
}
}
In your application logic, you can now throw the Bad Request exception with a message like so throw new BadRequestException("Invalid Email"). This will result in an exception thrown thus :
{
"timestamp": "2021-03-01T17:56:04.539+0000",
"status": 400,
"error": "Bad Request",
"message": "Invalid Email",
"path": "path to controller"
}
You can now create other custom exception classes for the different exceptions you want, following the above example and changing the value parameter in the #ResponseStatus, to match the desired response code you want. e.g for a NOT FOUND exception #ResponseStatus (value = HttpStatus.NOT_FOUND), Java provides the different HTTP status codes via the HttpStatus enum.
For more context
I hope this is detailed enough and helps someone :)
Possible duplicate of Spring Resttemplate exception handling Your code needs a controller advice to handle the exceptions from the service it is calling.
I am trying to create a REST API in the format which will accept request data with both JSON and MultipartFile type.
THis is my request which will be in following format in POSTMAN:
My POJO classes are as follows:
Class:Organisation
public class Organisation
{
priavet int org_id;
private MultipartFile organisationRegistrationDocument;
private Teachers[]
// getters and setters
}
Class: Teachers
class Teachers{
private String teacherId;
private MultipartFile teacherPhoto;
// getters and setters
}
My controller Class is as follows:
#RequestMapping(value="/test",method=RequestMethod.POST,headers = {"content-type=multipart/mixed","content-type=multipart/form-data"})
private ResponseEntity<Object> testUpload(#RequestBody Organisation org) {
return null;
}
Error Thrown from POSTMAN:
{
"timestamp": "2018-10-03T07:38:30.439+0000",
"status": 400,
"error": "Bad Request",
"message": "Required request part 'org' is not present",
"path": "/test"
}
So anyone can kindly guide me what can I am doing wrong due to which I am not able to achieve the desired result to process request of the above form?
I am trying to convert my application from spring to springboot, I have a problem in a web service parameter in springboot application.
This is my spring application:
#GET
#Path("/personels")
public Response getAllPersonels(#Context HttpHeaders headers, #Context Request request) {
String url = String.valueOf(((ContainerRequest) request).getRequestUri());
System.out.println(url);
return Response.status(Status.OK).entity(new Personel()).type(MediaType.APPLICATION_XML).build();
}
this is also my springboot application:
#RequestMapping("/personels")
public Response saveWebService(#Context HttpHeaders headers, #Context Request request) {
String url = String.valueOf(((ContainerRequest) request).getRequestUri());
System.out.println(url);
return Response.status(Status.OK).entity(new Personel()).type(MediaType.APPLICATION_JSON).build();
}
here is springboot error
{
"timestamp": 1500382494978,
"status": 500,
"error": "Internal Server Error",
"exception": "org.springframework.beans.BeanInstantiationException",
"message": "Failed to instantiate [javax.ws.rs.core.HttpHeaders]: Specified class is an interface",
"path": "/personels/"
}
These are just sample, but in the future I am going to use all request parameter(method,headers, entity,type..)
Is there an annotation for this problem?
Problem is about Jax-RS and spring mvc mixing. I noticed it thanks to #M. Deinum and #Viswanath Lekshmanan
finally I've changed method parameters like that;
#RequestMapping("/virtual")
public Response saveWebService(HttpServletRequest request){
}
I have the following controller advice to handle the exceptions within my app globally:
#ControllerAdvice
public class ExceptionHandlingController {
// Convert a predefined exception to an HTTP Status code
#ResponseStatus(value=HttpStatus.BAD_REQUEST) // 400
#ExceptionHandler(ConstraintViolationException.class)
public void ConstraintViolationExceptionHandler() {
//Nothing to do
}
}
The code below is the controller, which tries to save an object to the db (in the service layer). The class that object belongs to, has annotations that fail.
#RequestMapping(value = "/signup", method = RequestMethod.POST)
public void create(#RequestBody CustomUserDetails user, HttpServletResponse response) {
logger.debug("User signup attempt with username: " + username);
userDetailsServices.saveIfNotExists(user);
}
I expect the client to receive a 400 response when ConstraintViolationException is thrown.
When the method returns void , no response is returned. When I change it String and return a random text, I get 404 response back.
{
"timestamp": 1495489172770,
"status": 404,
"error": "Not Found",
"exception": "javax.validation.ConstraintViolationException",
"message": "Validation failed for classes [security.model.CustomUserDetails] during persist time for groups [javax.validation.groups.Default, ]\nList of constraint violations:[\n\tConstraintViolationImpl{interpolatedMessage='must match \"^(?!.*\\..*\\..*)[A-Za-z]([A-Za-z0-9.]*[A-Za-z0-9]){8,15}$\"', propertyPath=username, rootBeanClass=class com.boot.cut_costs.security.model.CustomUserDetails, messageTemplate='{javax.validation.constraints.Pattern.message}'}\n]",
"path": "/signup"
}
How can I make this return a simple BAD REQUEST message as it is defined for the #ExceptionHandler.
Note: ConstraintViolationExceptionHandler is hit!