I am writing a Spring Boot application. My controller has 2 custom request headers. I was executing a couple of tests only to find out that my application returns a '404' when the headers are not present.
I however was expecting this to lead to a '400' error?
Can anyone elaborate why this is happening? And how I should handle it properly? As in tell the consumer of the service the headers are missing?
#RestController("fundsConfirmationController")
#RequestMapping(
value="/accounts/{accountId}/funds-confirmations",
headers = {"X-CAF-MSGID", "X-AccessToken"}
)
public class FundsConfirmationController implements FundsConfirmationControllerI{
private FundsConfirmationServiceI fundsConfirmationService;
#Autowired
public FundsConfirmationController(FundsConfirmationServiceI fundsConfirmationService){
this.fundsConfirmationService = fundsConfirmationService;
}
#GetMapping(
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE
)
public ResponseEntity<?> fundsConfirmation(#RequestHeader(value="X-CAF-MSGID") String messageId,
#RequestHeader(value="X-AccessToken") String accessToken,
FundsConfirmationRequest requestParams) { ... }
2 solutions to do the same.
First using #RequestHeader with required false
#RequestMapping(value = "/{blabla}", method = RequestMethod.POST)
public void post(#RequestHeader(value="X-CAF-MSGID", required=false) String X-CAF-MSGID) {
if(X-CAF-MSGID == null) {
// Your JSON Error Handling
} else {
// Your Processing
}
}
Second using HttpServletRequest instead of #RequestHeader
#RequestMapping(value = "/{blabla}", method = RequestMethod.POST)
public void post(HttpServletRequest request) {
String X-CAF-MSGID = request.getHeader("X-CAF-MSGID");
if(X-CAF-MSGID == null) {
// Your JSON Error Handling
} else {
// Your Processing
}
}
Related
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"}.
I am trying to return response as JSON. After searching I found solution to add headers = "Accept=application/json" in RequestMapping. But still it is not working .
It is throwing error HTTP Status 406 "The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers."
Here is my controller code :
#RestController
public class EmployeeController {
private EmployeeService employeeService;
#Autowired(required = true)
#Qualifier(value = "employeeService")
public void setEmployeeService(EmployeeService employeeService){
this.employeeService = employeeService;
}
#RequestMapping(value = "/test",method = RequestMethod.GET)
public String test(){
return "{\"name\":\"xyz\"}";
}
#RequestMapping(value = "/employees",method = RequestMethod.GET,headers = "Accept=application/json")
public List<Employee> listEmployees(){
List<Employee> employees = this.employeeService.getEmployees();
return employees;
}
}
Where am I doing wrong?
The simple way to generate JSON, XML response is #ResponseBody annotation.
#RequestMapping(value =" /jsonPostSingle", method = RequestMethod.GET)
#ResponseBody
public PostModel generateJSONPostsingle(#ModelAttribute("postModel") PostModel postModel) {
if(postModel.getPostId() == 1) {
postModel.setTitle("post title for id 1");
} else {
postModel.setTitle("default post title");
}
return postModel;
}
This way you will be able to map your request to model class using #ModelAttribute.
Follow the complete tutorial Spring MVC : JSON response using #ResponseBody
I understand that you're trying to send a response from GET request of /employees.
if you are using Spring 3.1, try to use
#RequestMapping(value = "/employees",method = RequestMethod.GET, produces = "application/json")
instead of adding headers = "Accept=application/json"
More info:
if you want to specify type of data that will send with a request, you can use consumes attribute
example:
#RequestMapping(value="/foo", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
this will consumes and response with JSON type only
check this link about spring update http://spring.io/blog/2011/06/13/spring-3-1-m2-spring-mvc-enhancements/
Hope it helps
I need to throw a 405 for all the http methods that are not defined in my controller. I am using spring boot is there a generic way to write it so that i do not have to add a method on my controller to read all the HTTP methods currently i do not get any response but it throws a 200 OK. Below is my controller that only has GET and PUT. I want to throw a 405 for all other methods.
#RestController("CardController")
#RequestMapping("/user/v1")
public class CardController {
#Autowired
ICardService iCardService;
#RequestMapping(value = "/{cardHolderId}/cards", produces = "application/json; charset=utf-8", method = RequestMethod.GET)
#ResponseBody
public AllCardsVO getCards(#PathVariable("cardHolderId") final String id) {
return jsonObj;
}
#RequestMapping(value = "/{cardHolderId}/cards/{cardId}", produces = "application/json; charset=utf-8", method = RequestMethod.GET)
#ResponseBody
public CardVO getCard(#PathVariable("cardHolderId") final String cardHolderId,
#PathVariable("cardId") final String cardId){
return jsonObj;
}
#RequestMapping(value = "/{cardHolderId}/cards/{cardId}", produces = "application/json; charset=utf-8", method = RequestMethod.PUT)
#ResponseBody
public CardVO putCard(#PathVariable("cardHolderId") final String cardHolderId,
#PathVariable("cardId") final String cardId, #RequestBody final RequestVO requestVO) {
return jsonObj;
}
This is what I wrote in the controller but it does not work for PATCH.
#RequestMapping(value = "/**", produces = "application/json; charset=utf-8", method = { RequestMethod.OPTIONS,
RequestMethod.DELETE, RequestMethod.PATCH, RequestMethod.POST })
#ResponseBody
public void options(HttpServletResponse response) {
throw new MethodNotAllowedException();
}
Is there a generic way i can do this in spring boot some sort of configuration override or service having this method in every api controller does not seem correct. IF this is the only way how do i get the PATCH working. I am getting a response for PATCH even though i do not have that defined.
ANy help is appreciated.
Currently have a java spring application in development. It utilizes a ui along with restful apis which send/receive json via post requests.
Each api request needs to be validated with a token which will be sent with the request. This action is completed and a boolean is returned. Now the problem is when the boolean value is false(token not valid) I need to return a 401 error to the end user. Currently I am returning List which is being converted to json. How can I return some 401 error to the end user.
Example
//done
#RequestMapping(value = "/getSomething"
, method = RequestMethod.POST
, consumes = "application/json"
, produces = "application/json")
#ResponseBody
public List<Obj> getSomething(#RequestBody Input f) {
DAOImpl dAOImpl = (MapDAOImpl) appContext.getBean("DAOImpl");
Boolean res = dAOImpl.validateToken(f.session);
if(res) {
List<Obj> response = dAOImpl.getSomething(f.ID);
return response;
} else {
return new ResponseEntity<String>("test", HttpStatus.UNAUTHORIZED);
}
}
You just need to change your return type to ResponseEntity.
#RequestMapping(value = "/getSomething"
, method = RequestMethod.POST
, consumes = "application/json"
, produces = "application/json")
#ResponseBody
public ResponseEntity<?> getSomething(#RequestBody Input f) {
DAOImpl dAOImpl = (MapDAOImpl) appContext.getBean("DAOImpl");
Boolean res = dAOImpl.validateToken(f.session);
if(res) {
List<Obj> response = dAOImpl.getSomething(f.ID);
return new ResponseEntity<>(response, HttpStatus.OK);
}
return new ResponseEntity<String>("Unauthorized", HttpStatus.UNAUTHORIZED);
}
Note : I would recommend to pass proper JSON in error response so that client can parse and use if required.