Archive for 'jsf'

Validation errors and bean updates

Posted on Juni 3, 2010, under jsf.

One problem some people are facing in JSF is that a user inputs invalid data to a form which causes the related validators (or also converters) to fail and thus setting the valid property on every affected input component to false. This has the effect that those components will store this invalid value as a local value, which will also be rendered. This means that the component will not show the actual value from the managed bean, but the local value from its own state.

If the user now decides to change the values in the managed bean by some action in another form (or just by an AJAX request), the components won’t display the new values from the bean but their old local values. This problem actually causes some people to not use the JSF standard converters and validators, but to use their own ones in the related action methods.

To circumvent this problem the valid property as well as the local and the submitted value have to be reset on every affected input component. In JSF 1.2 the method resetValue() was introduced to achieve this in a convenient way. However if you’re using JSF 1.1, you will have to implement this yourself.

public void resetValue()
{
    setSubmittedValue(null);
    setValue(null);
    setLocalValueSet(false);
    setValid(true);
}

The fact that you will have to call this method before rendering on every input component which (maybe) has an invalid value and whose value has changed in the managed bean is kinda annoying. The best way to achieve this is to traverse the component tree either at the end of the action method which changes the value(s) in the bean or in a PhaseListener that will be called before the rendering occurs.

An example

Imagine you have the following facelet page:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets">

<h:head>
    <title>JSF - validation errors and bean updates</title>
</h:head>
<h:body>
    <h:form id="form1">
        <h:messages id="messages" />

        <h:inputText id="input" value="#{myBean.input}">
            <f:validateLength minimum="5" />
        </h:inputText>

        <h:commandButton value="Submit" action="#{myBean.action}" />
    </h:form>

    <h:form id="form2">
        <h:commandButton value="change input value"
                action="#{myBean.changeInput}" />
    </h:form>

    <ui:debug />
</h:body>
</html>

and the following managed bean:

@ManagedBean(name = "myBean")
@SessionScoped
public class MyBean
{

    private String input;

    public String getInput()
    {
        return input;
    }

    public void setInput(String input)
    {
        this.input = input;
    }

    public String action()
    {
        // process the valid user input

        return null;
    }

    public String changeInput()
    {
        // change input
        input = "changed input";

        return null;
    }

}

Now open the page in the browser, input for example “12″ into the text field (which is shorter than the minimum length) and click “Submit”. You will then get a validation error saying the inputted value is too short. If you now click the “change input value” button, the value in the managed bean will be changed, but the input field will still display “12″ from before. If you want the input field to display “changed input”, you will have to do the following on changeInput():

public String changeInput()
{
    // change input
    input = "changed input";

    // reset the input field
    UIInput field = (UIInput) FacesContext.getCurrentInstance()
            .getViewRoot().findComponent("form1:input");
    field.resetValue();

    return null;
}

Now the input field will display “changed input”. Of course this could also happen in a PhaseListener on before render view.

The problem with this solution is that all fields will have to have static Ids or will have to be bound to the bean using the binding attribute (not recommended) and furthermore this could end up in quite a lot of code, if you have lots of input components in the form. If you are using JSF 2.0, you can simplify this solution by using the tree visiting API (javax.faces.component.visit), however it rather seems like a workaround than a real solution.

Better solutions?

One solution would be to have a method on UIForm (or even on FacesContext?) saying resetValues(), which itself traverses the form’s children to reset all EditableValueHolders.

Another idea is to have a resetOnModelValueUpdate attribute on every input component which can be set to true or false. If it is set to true, the component will store the current version of the value from the managed bean in its state and check on the next postback for changes. If the value in the managed bean was changed by any other component or action, the component will automatically reset itself and use the new value from the bean.

Maybe something of this will make it in the JSF 2.1 spec. We’ll see!

Apache MyFaces Core 2.0.0 released

Posted on April 23, 2010, under jsf 2.0.

After the final release of the JSF 2.0 specification (JSR-314) in July 2009, the first alpha release in November 2009 and some beta releases in February and March 2010, Apache MyFaces Core 2.0.0 was released today. The release is 100% complaint with the JSR-314 specification and has passed Sun’s JSR-314 TCK.

You can download MyFaces Core 2.0.0 here or you can find it in the central Maven repository under Group ID “org.apache.myfaces.core”.

So now there is no reason anymore not to try it out yourself. You can check out all new features of JSF 2.0 with MyFaces Core 2.0.0 like e.g. composite components, the integrated Facelets view declaration language or the very easy AJAX support via f:ajax, just to mention a few here.

And please do not hesitate to file any issues you might run into in our bug tracker or to ask any questions you might have on our mailing list(s). We are very happy with every feedback we get!

You can also check out the related article on heise Developer (in German): JSF-Implementierung Apache MyFaces 2.0 erschienen

JSF 2.0: View parameters

Posted on April 10, 2010, under jsf 2.0.

One very cool new feature of JSF 2.0 are view parameters. If you are now wondering what I mean with a view parameter (or request parameter) – here’s the answer: Do you know those things at the end of an URL that often look like ?id=3&page=2, then you know what I mean. If not, take a look at this. The great advantage of these view parameters is that JSF’s URLs are now bookmarkable, because all values that are needed to display a certain page can be provided via the URL.

JSF 2.0 introduces a new UIInput component especially for view parameters called UIViewParameter. This component extends UIInput and thus has the same functionality as e.g. <h:inputText />. This means it can have converters and validators, its value is bound to a model (managed bean) and it goes through the JSF-lifecycle just as every other EditableValueHolder.

To define an UIViewParameter in your view you just have to add a <f:viewParam /> element inside your view metadata facet. Sounds complicated, but actually it is not, as you can see in the following Facelet page:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
 xmlns:h="http://java.sun.com/jsf/html"
 xmlns:f="http://java.sun.com/jsf/core"
 xmlns:ui="http://java.sun.com/jsf/facelets">

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

<h:head>
    <title>UIViewParameter example by jakobk</title>
</h:head>
<h:body>
    The view parameter's value is:
    <h:outputText value="#{myBean.input}" />
</h:body>
</html>

If you now access this page with http://localhost:8080/pathToWebapp/view.xhtml?input=abc, #{myBean.input} will be set to “abc”.

Very important for this feature to work is to use the JSF 2.0 built-in Facelets-2 view declaration language and not JSP or Facelets-1.x. Although the <f:viewParam /> tag is defined for JSP in the specification javadoc, the <f:metadata /> tag is missing and also I could not make it work. However I will dig into this and write another blog post about the JSP support soon. If you are currently using Facelets-1.x with JSF 2.0, just get rid of <view-handler>com.sun.facelets.FaceletViewHandler</view-handler> in your faces-config to upgrade to the JSF 2.0 built-in Facelets-2.

If you want your view parameter(s) to be required to render the view (which will be most likely, I guess), you just have to add required=”true” to <f:viewParam /> and your view will not accept any inputs or actions unless the view parameter is provided. In addition and as mentioned before, you can attach any kind of converters or validators (with the help of any <f:converter /> and/or <f:validator /> tags) to your <f:viewParam /> to verify the value. The following snippet shows a view parameter which only accepts non null Strings that are at least 3 characters long:

<f:viewParam required="true" name="input" value="#{myBean.input}">
    <f:validateLength minimum="3" />
</f:viewParam>

The UIViewParameter component also stores its value in the state, so that the value will also be available on the next postback request (most likely a clicked button or link). So you only need to provide your view parameter(s) once and not on every request.

On my opinion, view parameters are a really cool new feature of JSF. Of course, you were able to do the same thing with JSF 1.x and the request parameter map from ExternalContext, but this just was not very elegant and in case of conversion and validation also far more complicated.

More detailed information about view parameters can be found on the specification javadoc of <f:viewParam />.