Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSF List Converter

How do I write a converter for a list of items of class A in JSF2? I have written a converter for class A, but the items show up using the default toString() function: "A@hashcode".

I need to use a converter rather than a backing bean method so that validation can take place (Hibernate Validator).

more info

This is how I use the list:

<h:inputText id="destinations" value="#{rule.destinations}" converter="gr.panayk.vinyls.Destination"/>

Where #{rule.destinations} is of List<Destination> type. I am expecting a comma separated list of converted Destinations.

solution

I attach the List converter that BalusC proposed.

@FacesConverter(value="gr.panayk.vinyls.converter.DestinationList")
public class DestinationListConverter implements Converter
{
    @Override
    public Object getAsObject(final FacesContext context, final UIComponent component, final String values)
    {
        final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

        final List<Destination> result = new ArrayList<Destination>(); 
        for (String value : values.split(",", -1))
        {           
            final String trimmedValue = value.trim();

            final Set<ConstraintViolation<Destination>> violations = validator.validateValue(Destination.class, "data", trimmedValue);
            if (!violations.isEmpty())
            {
                throw new ConverterException(new FacesMessage(violations.iterator().next().getMessage()));
            }

            result.add(new Destination(trimmedValue));
        }       

        final Set<ConstraintViolation<Rule>> violations = validator.validateValue(Rule.class, "destinations", result);
        if (!violations.isEmpty())
        {
            throw new ConverterException(new FacesMessage(violations.iterator().next().getMessage()));
        }       

        return result;
    }

    @Override
    public String getAsString(final FacesContext context, final UIComponent component, final Object value)
    {
        if (value instanceof List<?>)
        {
            final StringBuffer result = new StringBuffer();

            final List<?> list = (List<?>) value;

            for (int i = 0; i < list.size()-1; i++)
            {               
                if (list.get(i) instanceof Destination)
                {
                    result.append(((Destination) list.get(i)).getData());
                    result.append(", ");
                }
                else
                {
                    throw new IllegalArgumentException( "Cannot convert " + value + " object to Destination in DestinationConverter." );
                }
            }

            if (!list.isEmpty())
            {
                if (list.get(list.size()-1) instanceof Destination)
                {
                    result.append(((Destination) list.get(list.size()-1)).getData());
                }
                else
                {
                    throw new IllegalArgumentException( "Cannot convert " + value + " object to Destination in DestinationConverter." );
                }
            }

            return result.toString();
        }
        else
        {
            throw new IllegalArgumentException( "Cannot convert " + value + " object to List in DestinationConverter." );
        }
    }
}
like image 604
Panayiotis Karabassis Avatar asked Oct 02 '11 11:10

Panayiotis Karabassis


People also ask

What is a JSF converter?

Conversion is the process whereby component data is transformed from strings to Java objects and vice versa, depending on whether the data is being sent from the client browser to the application server, or from the server to the browser.

Which JSF standard converters have their own tags?

JSF Converters The standard converters DateTimeConverter and NumberConverter both have their own tags, which allow you to configure the format of the component data by using the tag attributes.

What is converter in Java?

Converter is an interface describing a Java class that can perform Object-to-String and String-to-Object conversions between model data objects and a String representation of those objects that is suitable for rendering. Converter implementations must have a zero-arguments public constructor.


1 Answers

I have written a converter for class A, but the items show up using the default toString() function: "A@hashcode".

That can happen if you didn't explicitly declare the converter on the component. In for example <h:selectManyCheckbox> and <h:selectManyListbox> explicitly declaring the converter is mandatory as all JSF/EL knows is that the value is of type List, not List<A> (generic types are lost during runtime). If you don't declare a converter, then the values will be treated as String (as that's what HTML output and HTTP request parameter values default to).

E.g.

<h:selectManyCheckbox converter="aConverter">

with

@FacesConverter(value="aConverter", forClass=A.class)
public class AConverter implements Converter {

    // ...

}

Explicitly declaring the above converter is not necessary when you're using single-item inputs like <h:selectOneMenu> as the forClass would match it anyway.

like image 56
BalusC Avatar answered Oct 11 '22 15:10

BalusC