开发者

jsf 2.0 return http error code after failed GET parameter validation

I have this local URL: http://localhost:8084/Name/faces/Blah.xhtml?flkatid=AAA

and this is a segment from a facelet, that checks the parameter "flkatid" and assigns it to the bean:

    <f:metadata>
        <f:viewParam name="flkatid"
                     id="flkatid"
                     value="#{floKatBean.flkatid}"
                     required="true"
                     requiredMessage="URL incomplete"
                     validator="#{floKatBean.validateFlKatId}"
                     validatorMessage="URL incomplete or invalid"
                     >
        </f:viewParam>
        <f:event type="preRenderView" listener="#{floKatBean.init}"/>
        <f:event type="preRenderView" listener="#{floBean.holFloListe}"/>
    </f:metadata>

floKatBean.flkatid is an integer, thus the URL is invalid. A page is displayed, that tells this:

flkatid: 'AAA' must be a number consisting of one or more digits. flkatid: 'AAA' must be a number between -2147483648 and 2147483647 Example: 9346

JSF checks the parameter itself, because it knows that the bean element is an inte开发者_JAVA技巧ger. The custom validator is only called if the parameter is an integer.

Is it possible to get the server to return a HTTP error code, e.g. 403 (forbidden) without leaving the "standard JSF world" (or switch to RichFaces, MyFaces, SmileyFaces or whatever) ? I can't find anything in f:viewParam to "fail" the page. Maybe elsewhere?


You could do a ExternalContext#responseSendError() inside the validator. But this requires that the value is been declared as a String instead of Integer and that required="true" is been removed, all to prevent JSF default validation mechanism from doing the null/empty check and the conversion from String to Integer.

<f:metadata>
    <f:viewParam name="flkatid" value="#{floKatBean.flkatid}" 
        validator="#{floKatBean.validateFlKatId}" 
        validatorMessage="URL incomplete or invalid" 
    />
    ...
</f:metadata>

with

public void validate(FacesContext context, UIComponent component, Object value) 
    throws ValidatorException, IOException
{
    if (value == null || !((String) value).matches("\\d+")) {
        context.getExternalContext().responseSendError(
            403, (String) component.getAttributes().get("validatorMessage"));
    }
}

You could do the conversion in the init() method instead.

this.flkatidInteger = Integer.valueOf(this.flatkid);


I've found that the best way to do this (dealing with request parameters and sending useful HTTP responses) is to drop the f:viewParams entirely, and deal "manually" with the params in a preRenderView listener like this:

public void preRenderViewCheckParameters() throws IOException {
    if (!isPostback()) {
        flkatid = getFlkatidFromRequest();
        if (flkatid == null) {
            responseSendError(404, "URL incomplete or invalid!");
        }
    }
}
private Integer getFlkatidFromRequest(){
    try {
        return Integer.valueOf(getRequestParameter("flkatid"));
    } catch (NumberFormatException e) {
        return null;
    }
}

// util methods stolen from OmniFaces (check out this project, you'll love it):
// https://github.com/omnifaces/omnifaces/blob/master/src/org/omnifaces/util/Faces.java
public static String getRequestParameter(String name) {
    return FacesContext.getCurrentInstance().getExternalContext()
                       .getRequestParameterMap().get(name);
}
public static void responseSendError(int status, String message)
                           throws IOException {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    facesContext.getExternalContext().responseSendError(status, message);
    facesContext.responseComplete();
}

and then, in the view:

<f:metadata>
    <f:event listener="#{portariasMB.preRenderViewLoadPortaria}"
             type="preRenderView" />
</f:metadata>

It's a little bit more code maybe, but it's more straightforward, at least.

Also, doing this way you avoid weird problems with messages not being displayed, so... that's what I've been doing.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜