Trigger 404 in Spring-MVC controller?

JavaSpringSpring Mvc

Java Problem Overview


How do I get a Spring 3.0 controller to trigger a 404?

I have a controller with @RequestMapping(value = "/**", method = RequestMethod.GET) and for some URLs accessing the controller, I want the container to come up with a 404.

Java Solutions


Solution 1 - Java

Since Spring 3.0 you also can throw an Exception declared with @ResponseStatus annotation:

@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
    ...
}

@Controller
public class SomeController {
    @RequestMapping.....
    public void handleCall() {
        if (isFound()) {
            // whatever
        }
        else {
            throw new ResourceNotFoundException(); 
        }
    }
}

Solution 2 - Java

Starting from Spring 5.0, you don't necessarily need to create additional exceptions:

throw new ResponseStatusException(NOT_FOUND, "Unable to find resource");

Also, you can cover multiple scenarios with one, built-in exception and you have more control.

See more:

Solution 3 - Java

Rewrite your method signature so that it accepts HttpServletResponse as a parameter, so that you can call setStatus(int) on it.

http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping-arguments

Solution 4 - Java

I would like to mention that there's exception (not only) for 404 by default provided by Spring. See Spring documentation for details. So if you do not need your own exception you can simply do this:

 @RequestMapping(value = "/**", method = RequestMethod.GET)
 public ModelAndView show() throws NoSuchRequestHandlingMethodException {
    if(something == null)
	     throw new NoSuchRequestHandlingMethodException("show", YourClass.class);

    ...

  }

Solution 5 - Java

Since Spring 3.0.2 you can return [ResponseEntity<T>][1] as a result of the controller's method:

@RequestMapping.....
public ResponseEntity<Object> handleCall() {
    if (isFound()) {
        // do what you want
        return new ResponseEntity<>(HttpStatus.OK);
    }
    else {
        return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    }
}

(ResponseEntity<T> is a more flexible than @ResponseBody annotation - see [another question][2])

[1]: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/http/ResponseEntity.html "ResponseEntity<T>" [2]: https://stackoverflow.com/questions/22725143/what-is-the-difference-between-responseentityt-and-responsebody

Solution 6 - Java

you can use the @ControllerAdvice to handle your Exceptions , The default behavior the @ControllerAdvice annotated class will assist all known Controllers.

so it will be called when any Controller you have throws 404 error .

like the following :

@ControllerAdvice
class GlobalControllerExceptionHandler {
    @ResponseStatus(HttpStatus.NOT_FOUND)  // 404
    @ExceptionHandler(Exception.class)
    public void handleNoTFound() {
        // Nothing to do
    }
}

and map this 404 response error in your web.xml , like the following :

<error-page>
        <error-code>404</error-code>
        <location>/Error404.html</location>
</error-page>

Hope that Helps .

Solution 7 - Java

While the marked answer is correct there is a way of achieving this without exceptions. The service is returning Optional<T> of the searched object and this is mapped to HttpStatus.OK if found and to 404 if empty.

@Controller
public class SomeController {

    @RequestMapping.....
    public ResponseEntity<Object> handleCall(@PathVariable String param) {
        return  service.find(param)
                .map(result -> new ResponseEntity<>(result, HttpStatus.OK))
                .orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }
}

@Service
public class Service{
  
    public Optional<Object> find(String param){
        if(!found()){
            return Optional.empty();
        }
        ...
        return Optional.of(data); 
    }
    
}

Solution 8 - Java

If your controller method is for something like file handling then ResponseEntity is very handy:

@Controller
public class SomeController {
    @RequestMapping.....
    public ResponseEntity handleCall() {
        if (isFound()) {
            return new ResponseEntity(...);
        }
        else {
            return new ResponseEntity(404);
        }
    }
}

Solution 9 - Java

I'd recommend throwing HttpClientErrorException, like this

@RequestMapping(value = "/sample/")
public void sample() {
    if (somethingIsWrong()) {
        throw new HttpClientErrorException(HttpStatus.NOT_FOUND);
    }
}

You must remember that this can be done only before anything is written to servlet output stream.

Solution 10 - Java

This is a bit late, but if you are using Spring Data REST then there is already org.springframework.data.rest.webmvc.ResourceNotFoundException It also uses @ResponseStatus annotation. There is no need to create a custom runtime exception anymore.

Solution 11 - Java

Also if you want to return 404 status from your controller all you need is to do this

@RequestMapping(value = "/something", method = RequestMethod.POST)
@ResponseBody
public HttpStatus doSomething(@RequestBody String employeeId) {
    try {
        return HttpStatus.OK;
    } 
    catch (Exception ex) { 
         return HttpStatus.NOT_FOUND;
    }
}

By doing this you will receive a 404 error in case when you want to return a 404 from your controller.

Solution 12 - Java

Because it's always good to have at least ten ways of doing the same thing:

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class Something {
    @RequestMapping("/path")
    public ModelAndView somethingPath() {
        return new ModelAndView("/", HttpStatus.NOT_FOUND);
    }
}

Solution 13 - Java

Configure web.xml with setting

<error-page>
    <error-code>500</error-code>
    <location>/error/500</location>
</error-page>

<error-page>
    <error-code>404</error-code>
    <location>/error/404</location>
</error-page>

Create new controller

   /**
     * Error Controller. handles the calls for 404, 500 and 401 HTTP Status codes.
     */
    @Controller
    @RequestMapping(value = ErrorController.ERROR_URL, produces = MediaType.APPLICATION_XHTML_XML_VALUE)
    public class ErrorController {
    
    
        /**
         * The constant ERROR_URL.
         */
        public static final String ERROR_URL = "/error";
    
    
        /**
         * The constant TILE_ERROR.
         */
        public static final String TILE_ERROR = "error.page";
    
    
        /**
         * Page Not Found.
         *
         * @return Home Page
         */
        @RequestMapping(value = "/404", produces = MediaType.APPLICATION_XHTML_XML_VALUE)
        public ModelAndView notFound() {
    
            ModelAndView model = new ModelAndView(TILE_ERROR);
            model.addObject("message", "The page you requested could not be found. This location may not be current.");
    
            return model;
        }
    
        /**
         * Error page.
         *
         * @return the model and view
         */
        @RequestMapping(value = "/500", produces = MediaType.APPLICATION_XHTML_XML_VALUE)
        public ModelAndView errorPage() {
            ModelAndView model = new ModelAndView(TILE_ERROR);
            model.addObject("message", "The page you requested could not be found. This location may not be current, due to the recent site redesign.");
    
            return model;
        }
}

Solution 14 - Java

Simply you can use web.xml to add error code and 404 error page. But make sure 404 error page must not locate under WEB-INF.

<error-page>
    <error-code>404</error-code>
    <location>/404.html</location>
</error-page>

This is the simplest way to do it but this have some limitation. Suppose if you want to add the same style for this page that you added other pages. In this way you can't to that. You have to use the @ResponseStatus(value = HttpStatus.NOT_FOUND)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNA.View Question on Stackoverflow
Solution 1 - JavaaxtavtView Answer on Stackoverflow
Solution 2 - JavaJonatan IvanovView Answer on Stackoverflow
Solution 3 - Javamatt bView Answer on Stackoverflow
Solution 4 - Javamichal.kreuzmanView Answer on Stackoverflow
Solution 5 - JavaLu55View Answer on Stackoverflow
Solution 6 - Javauser957654View Answer on Stackoverflow
Solution 7 - JavaLiviu StirbView Answer on Stackoverflow
Solution 8 - JavaRalphView Answer on Stackoverflow
Solution 9 - JavammatczukView Answer on Stackoverflow
Solution 10 - JavapilotView Answer on Stackoverflow
Solution 11 - JavaAbdusSalamView Answer on Stackoverflow
Solution 12 - JavaJason DeMorrowView Answer on Stackoverflow
Solution 13 - JavaAtish NarlawarView Answer on Stackoverflow
Solution 14 - JavaRajith DelanthaView Answer on Stackoverflow