onsdag 19. mars 2014

XPages and SelectItem pecularities

I am always striving towards best practices when coding. This is not to say that I always know what is the best practice (often far from it) but when it comes to XPages I prefer Java over SSJS.

This struggle makes me often use a lot of extra (evening) time trying to find out how to do something the Java way. And this occasion was no exception.

Lately I have been working on an XPage which had a combobox for selecting between last year, current year or next year. All of course Integer values. Since hard coding values is not allowed (really, it isn't!) I had to generate values by code.

And here's the code:

package no.inforte.test;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import javax.faces.model.SelectItem;

public class YearBean implements Serializable {

    private static final long serialVersionUID = 1L;

    public List<SelectItem> getYears() {
        int thisYear = Calendar.getInstance().get(Calendar.YEAR);

        List<SelectItem> selectItems = new ArrayList<SelectItem>();

        selectItems.add(new SelectItem(new Integer(thisYear - 1), new Integer(thisYear - 1).toString()));
        selectItems.add(new SelectItem(new Integer(thisYear), new Integer(thisYear).toString()));
        selectItems.add(new SelectItem(new Integer(thisYear + 1), new Integer(thisYear + 1).toString()));
        return selectItems;
    }
}

And an excerpt from my xpage showing how to access the values using Expression Language (EL):


    <xp:comboBox
        id="comboYear"
        value="#{yearBean.currentYear}"
        style="width:100%">
        <xp:selectItems>
            <xp:this.value><![CDATA[${javascript:yearBean.years}]]></xp:this.value>
        </xp:selectItems>
        <xp:this.converter>
            <xp:convertNumber
                type="number"
                integerOnly="true">
            </xp:convertNumber>
        </xp:this.converter>
    </xp:comboBox>

The page shows up perfectly and 2013, 2014 and 2015 are available for selection.

Pick one and submit: Boom! Error! (what the...)


How come I get "Validation Error: Value is not valid"?

I started digging for documentation on what kind of values the <xp:selectitems> expect.

The help file itself was of no use. It simply explains how to "pipe-separated" strings for values...

But:
OpenNTF has released a XPages Control Documentation as part of the XPages Extension Library.
There is also a Domino Designer javadoc describing all the classes backing XPages.

Trying to squeeze out what was the problem with my page from this information however did only partly succeed. Neither did a Google search...

Suddenly (and I don't know how) it came to me that perhaps the number converter <xp:NumberConverter> really expects something floating-point-ish...


I changed my code accordingly:

package no.inforte.test;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import javax.faces.model.SelectItem;

public class YearBean implements Serializable {

    private static final long serialVersionUID = 1L;

    public List<SelectItem> getYears() {
        int thisYear = Calendar.getInstance().get(Calendar.YEAR);

        List<SelectItem> selectItems = new ArrayList<SelectItem>();

        selectItems.add(new SelectItem(new Double(thisYear - 1), new Integer(thisYear - 1).toString()));
        selectItems.add(new SelectItem(new Double(thisYear), new Integer(thisYear).toString()));
        selectItems.add(new SelectItem(new Double(thisYear + 1), new Integer(thisYear + 1).toString()));
        return selectItems;
    }
}
Note! The only change is that the SelectItem is now equipped with Double values.


And voila! Now it works without the validation error! :-)