I'm looking for a clean way to return customized 404 errorpages in Spring 4 when a requested resource was not found. Queries to different domain types should result in different error pages.
Here some code to show my intention (Meter is a domain class):
@RequestMapping(value = "/{number}", method = RequestMethod.GET)
public String getMeterDetails(@PathVariable("number") final Long number, final Model model) {
final Meter result = meterService.findOne(number);
if (result == null) {
// here some code to return an errorpage
}
model.addAttribute("meter", result);
return "meters/details";
}
I imagine several ways for handling the problem. First there would be the possibility to create RuntimeException
s like
@ResponseStatus(HttpStatus.NOT_FOUND)
public class MeterNotFoundExcption extends RuntimeException { }
and then use an exception handler to render a custom errorpage (maybe containing a link to a list of meters or whatever is appropriate).
But I don't like polluting my application with many small exceptions.
Another possibility would be using HttpServletResponse
and set the statuscode manually:
@RequestMapping(value = "/{number}", method = RequestMethod.GET)
public String getMeterDetails(@PathVariable("number") final Long number, final Model model,
final HttpServletResponse response) {
final Meter meter = meterService.findOne(number);
if (meter == null) {
response.setStatus(HttpStatus.NOT_FOUND.value());
return "meters/notfound";
}
model.addAttribute("meter", meter);
return "meters/details";
}
But with this solution I have to duplicate the first 5 lines for many controller methods (like edit, delete).
Is there an elegant way to prevent duplicating these lines many times?
The 404 error code is configured properly, but it will caused the “. htm” extension handling conflict between the “servlet container” and Spring's “DispatcherServlet“. To solve it, try change the 404. htm to other file extension, for example 404.
To have a custom 404 page for this error, we should edit our . htacess file, which is located under the root folder (usually inside the public_html folder for cPanel servers). If you can't find the . htacess file, you can simply create it.
In Spring Boot 1.4. x you can add a custom error page: If you want to display a custom HTML error page for a given status code, you add a file to an /error folder. Error pages can either be static HTML (i.e. added under any of the static resource folders) or built using templates.
The solution is much simpler than thought. One can use one generic ResourceNotFoundException
defined as follows:
public class ResourceNotFoundException extends RuntimeException { }
then one can handle errors within every controller with an ExceptionHandler
annotation:
class MeterController { // ... @ExceptionHandler(ResourceNotFoundException.class) @ResponseStatus(HttpStatus.NOT_FOUND) public String handleResourceNotFoundException() { return "meters/notfound"; } // ... @RequestMapping(value = "/{number}/edit", method = RequestMethod.GET) public String viewEdit(@PathVariable("number") final Meter meter, final Model model) { if (meter == null) throw new ResourceNotFoundException(); model.addAttribute("meter", meter); return "meters/edit"; } }
Every controller can define its own ExceptionHandler
for the ResourceNotFoundException
.
modified your web.xml file.Using following code.
<display-name>App Name </display-name> <error-page> <error-code>500</error-code> <location>/error500.jsp</location> </error-page> <error-page> <error-code>404</error-code> <location>/error404.jsp</location> </error-page>
Access this by following code.
response.sendError(508802,"Error Message");
Now add this code in web.xml.
<error-page> <error-code>508802</error-code> <location>/error500.jsp</location> </error-page>
You can map the error codes in web.xml like the following
<error-page>
<error-code>400</error-code>
<location>/400</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/404</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/500</location>
</error-page>
Now you can create a controller to map the url's that are hit when any of these error is found.
@Controller
public class HTTPErrorHandler{
String path = "/error";
@RequestMapping(value="/404")
public String error404(){
// DO stuff here
return path+"/404";
}
}
For full example see my tutorial about this
Simple answer for 100% free xml:
Set properties for DispatcherServlet
public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { RootConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] {AppConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
//that's important!!
@Override
protected void customizeRegistration(ServletRegistration.Dynamic registration) {
boolean done = registration.setInitParameter("throwExceptionIfNoHandlerFound", "true"); // -> true
if(!done) throw new RuntimeException();
}
}
Create @ControllerAdvice:
@ControllerAdvice
public class AdviceController {
@ExceptionHandler(NoHandlerFoundException.class)
public String handle(Exception ex) {
return "redirect:/404";
}
@RequestMapping(value = {"/404"}, method = RequestMethod.GET)
public String NotFoudPage() {
return "404";
}
}
Create 404.jsp page with any content
That's all.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With