Saturday, August 18, 2012

When Seam's bijection fails for < h:selectManyCheckbox >

For simple object reference, Seam's Injection saves you from having to type the getter and setter methods.   When a form input is selected, JSF goes through the process of conversion and validation.   If validation fails, the form input is not submitted and you get the conversion error.  Therefore, when you were injecting and outjecting an object of your design, you have to use if you are using as your option choices or you have to take care of the conversion in the code.  With the annotations like @Factory and @In @Out, Seam's binary injection has eased us from having to write extra steps of code.

However, this does not work with tag.  There is a couple of ways one could run into the problem with .  There were so many times I had trouble with validation errors for because the rendering of is different from those of other JSF tags.  And one other problem that I came across is Seam's injection does not work well for .

For example, you have a select many check box where you want the user to select at least one or more bank account.  So, you have an entity called Bank Account.  Technically, you should be able to do it easily via the following code:


In the Stateful Bean,

    @In(required=false, create=true)
    @Out(required=false)
    private List selectedAccount;


In JSF code,
        <h:selectManyCheckbox value="#{selectedAccount}"
                        layout="pageDirection">
            <s:selectItems value="#{bankAccountList}" var="b"
                            label="#{b.accountName}" />
            <s:convertEntity />
        </h:selectManyCheckbox>


If you do so, you will get the conversion error, JSF complaining that you can't convert an array of string to an array of your object, in this case is List.  Since is there, you would image that the conversion should automatically happen.  But this is not the case, as you do not know how exactly Seam implemented @In and @Out.  So, the work around is to use getter and setter method instead as below:

In the Stateful Bean,

    @In(required=false, create=true)
    @Out(required=false)
    private List selectedAccount;

    public List getSelectedPartners() {
        return selectedAccount;
    }

    public void setSelectedPartners(List selected) {
        selectedAccount = selected;
    }


In JSF code,
        <h:selectManyCheckbox value="#{nameOfYourBean.selectedAccount}"
                        layout="pageDirection">

            <s:selectItems value="#{bankAccountList}" var="b"
                            label="#{b.accountName}" />
            <s:convertEntity />
        </h:selectManyCheckbox>
   
Using the getter and setter method make sure that, a new array list of BankAccount objects are created every time the form is submitted.  So, it ensures that nothing unexpected happens.  From my experience with Seam, annotations are good, but hiding the complexity to ease the programmers exposes us to another layer of debugging the framework and making sure it works as intended.  In a lot of cases, getters and setters solve the problem that you have with @In and @Out.

Happy programming!.




           

No comments:

Post a Comment