Search code examples
javaerror-handlingjsf-2.2view-scope

Write 404 on ViewScop and display error file without redirect in JAVA JSF


How do I throw an error 404 if the ID was not found without sending a 302 redirect.

In my ViewScop I do a select and would like to return an error 404 with showing the content of the 404 error page (404.xhtml).

I tried the following which gives me justs a 302 redirect to the 404.xhtml:

@PostConstruct
public void initialize() {
    data = service.select(id.getValue());
    if (data == null) {
        FacesContext context = FacesContext.getCurrentInstance();
        context.getExternalContext().setResponseStatus(404);
        context.responseComplete();
        try {
            context.getExternalContext().redirect("/404.xhtml");
        } catch (IOException ex) {
        }
    }
}

Actually if I comment the redirect out, I get the correct error code, but still the called xhtml file gets rendered.

What is the best approach here? There are a lot of answers in SO but I didn't find one which was working for me.


EDIT: Here some other answers from SO, which was suggested by @Ben where with I found the correct answer:


Solution

  • Thx to @Ben I searched again and found the correct answer: How to throw 404 from bean in jsf !

    The solution is to use .dispatch() on an ExternalContext.

    dispatch

    public abstract void dispatch(String path) throws IOException

    Dispatch a request to the specified resource to create output for this response.

    Servlet: This must be accomplished by calling the javax.servlet.ServletContext method getRequestDispatcher(path), and calling the forward() method on the resulting object.

    If the call to getRequestDisatcher(path) returns null, send aServletResponse SC_NOT_FOUND error code.

    Parameters:
    path - Context relative path to the specified resource, which must start with a slash ("/") character

    Throws:
    FacesException - thrown if a ServletException occurs
    IOException - if an input/output error occurs

    So my solution looks like that now:

    @PostConstruct
    public void initialize() {
        data = service.select(id.getValue());
        if (data == null) {
            try {
                FacesContext context = FacesContext.getCurrentInstance();
                ExternalContext externalContext = context.getExternalContext();
                externalContext.setResponseStatus(HttpServletResponse.SC_NOT_FOUND);
                externalContext.dispatch("/404.xhtml");
                context.responseComplete();
            } catch (IOException ex) {
            }
        }
    }