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).
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.
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." );
}
}
}
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With