Spring MVC Controller respond on case of error - spring

I have the following controller method :
#RequestMapping(value = "/", method = RequestMethod.POST)
#ResponseStatus(value = HttpStatus.CREATED)
#ResponseBody
public AbstractIngoingMessage postMessages(Locale locale, Model model, HttpServletRequest request, HttpServletResponse response) {
logger.info(String.format(
Constants.LogMessages.NEW_POST_REQUEST_FROM_IP,
request.getRemoteAddr()));
AbstractIngoingMessage handledMessage = dispatchMessageHandling(request);
return handledMessage;
}
problem is, when an error occurred on the method the response im sending back is still "CREATED"
is there a way to respond with "ERROR" ?

Related

Spring MVC - Stop redirect in Controller function

I have a Spring MVC Controller and a PUT mapping that consumes JSON. I receive the JSON and everything just fine, the problem is whenever I fire off the JSON the mapper wants to redirect to the URL, giving me error 500 because the server can't find any template for the URL. How can I stop Spring MVC from trying to redirect to the URL and just receive the JSON?
My relevant Controller code :
#RequestMapping(value = "admin/users/VMs", method = RequestMethod.PUT, consumes = "application/json")
public void removeVM(#RequestBody ManageVMRequest packet, Authentication authentication) {
System.out.println(packet.getVm());
System.out.println(packet.getUser_id());
}
You can try to return ResponseEntity<Void>
#RequestMapping(value = "admin/users/VMs", method = RequestMethod.PUT, consumes = "application/json")
public #ResponseBody ResponseEntity<Void> removeVM(#RequestBody ManageVMRequest packet, Authentication authentication) {
System.out.println(packet.getVm());
System.out.println(packet.getUser_id());
return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
}

Spring mvc - Configuring Error handling for XML and JSON Response

i have one REST API method :which will return Xml as response . Just for simplicity assume it throws simple Exception.
#RequestMapping(value = "machine/xmlData", method = RequestMethod.GET, produces = "application/xml")
public ResponseEntity<String> getXml(HttpServletRequest request)
throws Exception {
return getDataFromService();
}
Now i am handling the Exception in REST Controller like this.
This is generic Exception Handle method, for other API methods as well.(Xml or JSON Response)
#ExceptionHandler(Exception.class)
#ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
public ResponseEntity HandleException(Exception ex, HttpServletRequest request) {
ex.printStackTrace();
// here logic to generate Custom error Object
return new ResponseEntity<Object>(customErrorObject, HttpStatus.INTERNAL_SERVER_ERROR);
}
Case 1: Accept :"application/xml" and valid Response from Service
Everything works fine.
Case 2: Accept :"application/xml" and Exception from Service
then i get 406 Not Representable
As per my understanding it is
because ResponseEntity from HandleException is JSON and accept header
is "application/xml" thats why i am getting 406.
Is there anyway that i can send the error Response from HandleException method as xml and json ?
I know on REST API methods we can define something like this produces={"application/json","application/xml"} i am struggling to put this on HandleException Method.
Any tip would be of great help.
Thanks.
You could take advantage of the spring-mvc HttpMessageConverters by using the #ResponseBody annotation( https://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc). This annotation is responsible for choosing the correct messageConverter for a given response type.
For your response to be xml or json compatible you need to do the following:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class WrappedExceptionResponse {
public String respone;
public String getRespone() {
return respone;
}
public void setRespone(String respone) {
this.respone = respone;
}
}
And change your exception handler method to
#ExceptionHandler(Exception.class)
#ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
public #ResponseBody WrappedExceptionResponse HandleException(Exception ex, HttpServletRequest request) {
// ex.printStackTrace();
// here logic to generate Custom error Object
WrappedExceptionResponse resp=new WrappedExceptionResponse();
resp.setRespone(ex.getMessage());
return resp;
And then your exception response would be dependent on the content-type you give.

"org.springframework.web.servlet.PageNotFound handleHttpRequestMethodNotSupported" Request method 'POST' not supported

I am using angular JS and Spring MVC+Spring Security in my application. When using $http like below:
$http.post('/abc/xyz/'+catalogId);
it is giving below error:
org.springframework.web.servlet.PageNotFound handleHttpRequestMethodNotSupported
WARNING: Request method 'POST' not supported.
Moreover I've put POST in my controller as well:
#RequestMapping(value = "/xyz/{catalogId}", method = RequestMethod.POST)
public #ResponseBody List<Category> getCategorybyCatalogId(#PathVariable(value = "catalogId") long catalogId, ModelMap modelMap,
HttpSession session) throws IOException {
if (catalogId != 0) {
return menuService.getCategorybyCatalogId(catalogId);
} else {
return null;
}
}
this problem started coming when I added spring security config class.
Please help!!

Adding #ModelAttribute results in 400 (Bad Request) in Delete Request

I can submit a delete request fine with the following:
#RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public ResponseEntity<Result> deleteTest(#PathVariable String id) {
return new ResponseEntity<>(Result.Success("Hi " + id + "!!!", null), HttpStatus.OK);
}
However, when I add an #ModelAttribute variable, I get 400 (Bad Request) as the http response code:
#RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public ResponseEntity<Result> deleteTest(#PathVariable String id, #ModelAttribute("authUser") User authUser) {
return new ResponseEntity<>(Result.Success("Hi " + id + "!!!", null), HttpStatus.OK);
}
This #ModelAttribute is working fine with a put request handler I have in my #RestController but not in this delete request.
Here's the #ModelAttribute code:
#ModelAttribute("authUser")
public User authUser(#AuthenticationPrincipal SpringAuthUser springAuthUser) throws Exception {
User user = ConstantsHome.userprofileMgr.getUserByUserId(springAuthUser.getUsername(), true, true);
user.updateRights(null);
request.getSession().setAttribute(ConstantsHome.USEROBJECT_KEY, user);
return user;
}
Why would adding #ModelAttribute cause a delete request to return a 400 (Bad Request) http response?
I'm using spring-web-4.1.4 & spring-security-4.0.3
I digged a little and found that specifying a #PathVariable of "id" somehow attaches it to the #ModelAttribute variable (as a Long(!) instead of a String as I specified). I then came across this post that lead me to different ways to resolve the issue :
Values of #PathVariable and #ModelAttribute overlapping.
Ended up with this as a method declaration (replaced "id" with "userId"):
#RequestMapping(value = "/{userId}", method = RequestMethod.DELETE)
public ResponseEntity<Result> deleteUser(#PathVariable String userId,
#ModelAttribute("authUser") User authUser) {
...
}
Hopefully this will help someone else quickly that might run into this issue instead of spending a day trying to figure it out...

Spring 3.2 forward request with new object

I'm trying to forward a request from one controller to another controller and set a object in request so that the forwarded controller can use it in #RequestBody.
Following is the exact scenario:
Twilio calls a controller method with data sent by client as following:
#RequestMapping(value = "/sms", method = RequestMethod.POST)
public String receiveSms(#RequestParam("Twiml") String twiml,
HttpServletRequest request,
HttpServletResponse response) {
//TODO - Create new instance of Activity and populate it with data sent from client
return "forward:/activity/new";
}
Now, I want to forward this request to ActivityController which already handles the request from web/rest clients.
ActivityController.java has a method with following signature:
#RequestMapping(value = "/activity/new", method = RequestMethod.POST)
public ResponseEntity<Activity> updateLocation(
#RequestBody Activity activity) {
}
Is it possible? If yes, how?
Thanks,
Create the object and add it to the request as an attribute in the first controller,
request.setAttribute("object",new OwnObject()),
return "forward:/activity/new";
In the updateLocation Method retrieve that object from the request
#RequestMapping(value = "/activity/new", method = RequestMethod.POST)
public ResponseEntity<Activity> updateLocation(
#RequestBody Activity activity, HttpServletRequest request) {
OwnObject o = (OwnObject) request.getAttribute("object");
}

Resources