Spring MVC default #RequestMapping to catch unmatched URL - java

I have this Controller
#Controller
#RequestMapping(value = "/v1.0/user")
public class UserController {
#RequestMapping(value = "/findOne/{id}", method = RequestMethod.GET)
public #ResponseBody String findOne(#PathVariable("id") Integer id) {
log.info("findOne");
return "found URL";
}
}
Which will match the URL: http://localhost:8080/v1.0/user/findOne/4
But if my path varibale is not correct: http://localhost:8080/v1.0/user/findOne/4A
The I get nothing. Not even an error. It's as if Spring swallowed the URL.
I added
#RequestMapping(value = "/.*", method = RequestMethod.GET)
public #ResponseBody String redirectEverythingOtherThanTest(){
log.info("no url matched");
return "badly formed URL for Users";
}
Again I get nothing. What I'm trying to accomplish is for each Controller to have a unique message when the URL does not match.

In the end in each of my Controller classes I added
#ExceptionHandler(Exception.class)
public #ResponseBody String handleException(Exception e, HttpServletRequest request, HttpServletResponse response) {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return e.getMessage();
}
And this will catch all exceptions and I can treat it as a catch all.

Related

Return web page body from Spring end point

Is it possible to return html web page as very long string from Spring endpoint? For example:
#PostMapping(value = "/redirect/{token}", consumes = { MediaType.APPLICATION_XML_VALUE,
MediaType.APPLICATION_JSON_VALUE },
MediaType.APPLICATION_JSON_VALUE })
public ModelAndView handleRedirectMessage(#PathVariable("token") String token,
#RequestBody PaymentTransaction transaction, HttpServletRequest request) throws Exception {
String body = "<html>.....</html>";
return new ModelAndView("redirect:" + body);
}
I would like to return html page body when user opens the Spring end point into the web browser.
As suggested by #user2478398
#PostMapping(value = "/redirect/{token}",produces = MediaType.TEXT_HTML_VALUE)
public String handleRedirectMessage(#PathVariable("token") String token,
#RequestBody PaymentTransaction transaction, HttpServletRequest request) throws Exception {
String body = "<http>.....</html>";
return body;
}
Try to use produce as - produces = MediaType.TEXT_HTML_VALUE
I have changed your code and you can changed it your way , this is an idea to resolved you problem
#PostMapping(value = "/redirect/{token}",produces = MediaType.TEXT_HTML_VALUE)
public ModelAndView handleRedirectMessage(#PathVariable("token") String token,
#RequestBody PaymentTransaction transaction, HttpServletRequest request) throws Exception {
String body = "<HTML><body>Now you can redirect just do it man !!.</body></HTML>";
return new ModelAndView("redirect:" + body);
}

Spring Rest Service Call returning error on line 1 at column 1: Document is empty

I wrote a REST Call which will return health status when called
#RestController
#RequestMapping(value = "/account")
public class HealthCheckController {
protected final Logger log = LoggerFactory.getLogger(this.getClass());
#RequestMapping(value = "/health", method = RequestMethod.GET, produces = { "application/json" })
#ResponseStatus(HttpStatus.OK)
#ApiOperation(value = "Returns the health status of the application", notes = "Load balancer user this to confirm the health of the node")
public #ResponseBody String getHealth(HttpServletRequest request, HttpServletResponse response) throws Exception {
log.info("***" + RequestCorrelation.getId() + "***" + "HealthCheckController - getHealth () Called");
return "{\"health\":{\"SERVICES\":\"OK\"}}";
}
}
When I open this in swagger or postman it returns proper response. But when i hit this URL in chrome browser i am seeing
This page contains the following errors:
error on line 1 at column 1: Document is empty
Below is a rendering of the page up to the first error.
Why so? and how to fix this?
Having the same issue. Have an object with the following class annotations and method:
#Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
#Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
#GET
#Path("version")
public String getVersion() { return "v1"; }
Added MediaType.TEXT_PLAIN to the end of the #Produces annotation. Didn't work.
Moved it the beginning of the #Produces annotation. Didn't work.
Moving/Adding it to the method resolved the issue for me. Your client will need to be able to accept that media type as well.
#GET
#Path("version")
#Produces({MediaType.TEXT_PLAIN})
public String getVersion() { return "v1"; )
HTH
In your getHealth() method, you're returning a String but in your #RequestMapping annotation, you specify that your method will produce JSON.
Try one of these:
#RequestMapping(value = "/health", method = RequestMethod.GET, produces = { "text/plain" })
//Now, pass Accept = "text/plain" in the request header:
or
#RequestMapping(method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
public List<String> getHealth(..) {
/*
...
*/
ArrayList<String> list=new ArrayList();
list.add("Health OK");
return list;
}
This would give you
["Health OK"] in the response.
Try to return not a String but
return new ResponseEntity<>(yourString, HttpStatus.OK);
and also change this
public #ResponseBody String getHealth(HttpServletRequest request, HttpServletResponse response) throws Exception {
to this
public #ResponseBody ResponseEntity<String> getHealth(HttpServletRequest request, HttpServletResponse response) throws Exception {
And if it doesn't work, try to add .xml or .json to the end of your URL, when you accessing it in browser.

Spring MVC #ExceptionHandler method in controller invoking in success case

I'm trying to catch an error scenario but I'm getting an exception in all cases.
Below is my code snippet:
#RequestMapping(value = "/config/file/data", method = RequestMethod.GET)
#ResponseBody
#ExceptionHandler(RestClientException.class)
#ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Not Found")
public void restClientException()
{
//do nothing
}
public List<myfile> getAllmyfiles() throws RestClientException
{
return myfileService.getAllmyfiles();
}
try this :
#ExceptionHandler(RestClientException.class)
#ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Not Found")
public void restClientException()
{
//do nothing
}
#RequestMapping(value = "/config/file/data", method = RequestMethod.GET)
#ResponseBody
public List<myfile> getAllmyfiles() throws RestClientException
{
return myfileService.getAllmyfiles();
}
you shouldn't use a #RequestMapping with an #ExceptionHandler : the method annotated with #ExceptionHandler is automatically invoked when the specified exception is thrown

get modelandview object in another controller

I am working to pass data from one controller to another.
I have one class that is annotated with #ControllerAdvice that is used to handle all exception of application.
I am processing exception and adding them to custom class then in ModelAndView I am adding that and passing to another controller using redirect.
And in that controller I want that added object but I don't have much idea about it how to get that object. I have tried some trick but did not get success.
Code:
ExceptionHandler class:
#ControllerAdvice
public class DefaultExceptionHandler {
#Autowired
private CPro cPro;
private static final Logger LOG = LoggerFactory.getLogger(DefaultExceptionHandler.class);
#RequestMapping(produces = {MediaType.APPLICATION_JSON_VALUE})
#ExceptionHandler(Exception.class)
#ResponseStatus(value = INTERNAL_SERVER_ERROR)
#ResponseBody
public ModelAndView handleException(Exception ex) {
ModelAndView modelAndView = new ModelAndView("redirect:/");
String exceptionType = ex.getClass().getSimpleName();
DefaultExceptionHandler.LOG.error("Internal Server Exception", ex);
ErrorResponse response = new ErrorResponse();
if (ex.getCause() != null) {
response.addSimpleError(exceptionType, ex.getCause().getMessage(), cPro.getProName());
} else {
response.addSimpleError(exceptionType, ex.getMessage(), cPro.getProName());
}
modelAndView.addObject("processingException", response);
return modelAndView;
}
}
my home controller:
#RequestMapping(value = "/", method = RequestMethod.GET)
public String getHomePage(#ModelAttribute("processingException") ErrorResponse errorResponse, Model model) {
// I want to get object data of processingException added in exception handler using ModelAndView
model.addAttribute("processingException", errorResponse.getError() == null ? null : errorResponse);
return "upscale"; //here upscale.html redirection
}
Does anyone have idea that how to get that object data in my controller ?
Thanks.
After a lot googling and searching various forums and article, I found some solution. I have combined data and code of various forums I have made my requirement fulfill.
We can use FlashMap for that. Just get context of request and add FlashMap and add other data to FlashMap as well.
Code:
#ControllerAdvice
public class DefaultExceptionHandler {
#Autowired
private CPro cPro;
private static final Logger LOG = LoggerFactory.getLogger(DefaultExceptionHandler.class);
#ExceptionHandler(Exception.class)
public String handleException(Exception ex, HttpServletRequest request) throws IOException {
DefaultExceptionHandler.LOG.error("Internal Server Exception", ex);
String exceptionType = ex.getClass().getSimpleName();
ErrorResponse response = new ErrorResponse();
if (ex.getCause() != null) {
response.addError(exceptionType, ex.getCause().getMessage(), cPro.getProName());
} else {
response.addError(exceptionType, ex.getMessage(), cPro.getProName());
}
FlashMap outputFlashMap = RequestContextUtils.getOutputFlashMap(request);
if (outputFlashMap != null) {
outputFlashMap.put("processingException", response);
}
return "redirect:/";
}
}
and other hand, in controller use ModelAttribute to get data that is sent from exception handler method.
code:
#RequestMapping(value = "/", method = RequestMethod.GET)
public String getHomePage(Model model, #ModelAttribute("processingException") Object processingException) {
if (processingException instanceof ErrorResponse) {
model.addAttribute("processingException", ((ErrorResponse) processingException).getError());
} else {
model.addAttribute("processingException", null);
}
return "upscale"; //here upscale.html redirection
}
After all bingo.. Done my work.
If anyone have still better idea on it then still welcome..
Thanks guys.
You could make a workaround like this:
public ModelAndView handleException(Exception ex, HttpServletRequest req) {
//...
ModelAndView modelAndView = new ModelAndView("forward:/");
//...
req.setAttribute("processingException", response);
Then in your Controller Method you have access to HttpServletRequest and get the Attribute (Object):
public String getHomePage(#ModelAttribute("processingException", HttpServletRequest req)
{
//....
req.getAttribute("processingException");

Inconsistent error: Request method 'POST' not supported

Using Spring REST API [Spring MVC]
Scenario:
when request comes to the EmployeeController , it is forced to forward the request/response to another URI,if it falls under a specific logic.
The controller method has RequestMapping set with 'RequestMethod.POST' and the destination controller- SpecialController has the method named invalidRequest() that has RequestMapping set with 'RequestMethod.GET'
EmployeeController:
#RestController
#RequestMapping(value = "/employee")
public class EmployeeController {
String res = null;
#RequestMapping(value = "/update", method = RequestMethod.POST)
public String updateEmployeeDetails(HttpServletRequest httpRequest, HttpServletResponse httpResponse,
#Valid #RequestBody Employee emp) throws ServletException, IOException {
// based on logic, forward the request to a different controller that handles invalid request
if( ...) { // condition checking
RequestDispatcher requestDispatcher = httpRequest.getServletContext().getRequestDispatcher("/invalidRequest");
requestDispatcher.forward(httpRequest, httpResponse);
}
if(..someother condition..) {
String res = "something";
}
return res;
Destination Controller:
#RestController
#RequestMapping(value = "/invalidRequest")
public class SpecialController {
#RequestMapping(value = "", method = RequestMethod.GET)
public String invalidRequest(HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
httpResponse.setStatus(401);
return "invalidRequest";
}
}
Question: Inconsistency Problem [Actual Problem]:
In 90% of the times, this is working, but a few times very rarely, I get the below error.
If I am getting this error always, then it would have made some meaning and I would have the below mentioned 'possible fix'
But since it is working most of the times, and not working only sometimes, I need your help in finding out why?
> org.springframework.web.HttpRequestMethodNotSupportedException:
> Request method 'POST' not supported
> at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.handleNoMatch(RequestMappingInfoHandlerMapping.java:198)
> at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lookupHandlerMethod(AbstractHandlerMethodMapping.java:286)
> at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:233)
> at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:56)
> at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:300)
> at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1101)
> at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:916)
> at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
> at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
> at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
possible fix if the error was consistent:
#RestController
#RequestMapping(value = "/invalidRequest")
public class SpecialController {
#RequestMapping(value = "", method = RequestMethod.GET)
public String invalidRequest(HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
httpResponse.setStatus(401);
return "invalidRequest";
}
#RequestMapping(value = "", method = RequestMethod.POST)
public String invalidRequest2(HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
return invalidRequest(httpRequest, httpResponse);
}
}

Categories

Resources