12

Let's say that I have an application which manages users. You can add new user, delete them, edit detail etc. Each user has na ID and has detail page on URL like this:

..../user/detail.jsf?id=123

Now, what should happen if user with ID 123 does not exists? I think that natural reaction would be 404 standard error. Exactly the same as is outputed when you make some typo in URL (like /user/dtail.jsf). So the question is: is there such method?

Or maybe is this reaction (404) appropriate?

Thanks.

Tomik
  • 317
  • 4
  • 12

3 Answers3

14

Just attach a validator to the id view parameter and if validation fails, set error code 404 on the response.

e.g.

Consider this simple Facelet:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">

    <f:metadata>
        <f:viewParam id="id" name="id" value="#{myBean.id}" validator="#{myBean.validate}"/>
    </f:metadata>

    <h:body>

        <h:outputText value="#{myBean.id}"/>

    </h:body>

</html>

And the following backing bean:

@ManagedBean
@ViewScoped
public class MyBean {

    private Long id;

    public void validate(FacesContext context, UIComponent component, Object object) {
        // Do some validation
        // And if failed:
        context.getExternalContext().setResponseStatus(404);
        context.responseComplete();
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

}
Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
  • 6
    In JSF2 there's [`ExternalContext#setResponseStatus()`](http://download.oracle.com/javaee/6/api/javax/faces/context/ExternalContext.html#setResponseStatus%28int%29). No need for casting anymore! :) There's by the way also an [`ExternalContext#responseSendError()`](http://download.oracle.com/javaee/6/api/javax/faces/context/ExternalContext.html#responseSendError%28int,%20java.lang.String%29). – BalusC Feb 04 '11 at 23:56
  • Nice, I actually did scan through the list of methods in ExternalContext but completely missed it. Thanks! Updated the answer as this is the more straightforward solution. – Arjan Tijms Feb 05 '11 at 00:33
  • Thanks for the solution, it was helpful. Without BalusC solution I used forwarding to nonexisten location which produced almost identical result. – Tomik Feb 05 '11 at 22:34
1

(I ended up here searching for something similar but here's another pattern I used on a similar problem)

The Validation/ExternalContext response above is a very good way to handle it, alternatively (since you are already inside the context) you can handle the error when parsing in the parameters from the request and deal with it internally. I think it is more of how you want to handle it in your flow than a "here's a better solution"

//Inside "SomeManagedBean"
  public String getParam()
  {
    String value = (String) FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("key");
    if(value == null)
      return "key not Exist";
    else
      return value;

  }

//JSF 2.0 Source (something.xhtml) ... ...

I think the above is generally easier to work with inside the framework (you don't have to send out to an error page and disrupt the flow), but really it is simply an architectural decision. Both solutions are similar, it is just a question of breaking the flow or internal handling. Either way the ExternalContext is your friend.

Daniel B. Chapman
  • 4,647
  • 32
  • 42
1

As mentioned, you can get the context from within a managed bean. I tried the validator approach, but for me it wasn't applicable since I was using two parameters to initialize my bean, and I do want to throw a 404. For me .setResponseStatus didn't throw the 404-page. Just gave a non-informative browser page. So I used the responseSendError instead.

Darknight
  • 43
  • 6
  • Help me more because it shows the error page. Just to complete, here is the code: ((HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse()).sendError(HttpServletResponse.SC_NOT_FOUND); – Erveron Sep 06 '12 at 22:49