I've written a custom converter as follows:
@FacesConverter(value = "orderListConverter")
public class OrderListConverter implements Converter {
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
Object ret = null;
if (component instanceof OrderList) {
Object list = ((OrderList) component).getValue();
ArrayList<ExampleEntity> al = (ArrayList<ExampleEntity>) list;
for (Object o : al) {
String name = "" + ((ExampleEntity) o).getName();
if (value.equals(name)) {
ret = o;
break;
}
}
}
return ret;
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value)
{
String str = "";
if (value instanceof ExampleEntity) {
str = "" + ((ExampleEntity) value).getNumber();
}
return str;
}
}
My ExampleEntity is implemented as follows:
public class ExampleEntity {
private String name;
private int number;
public ExampleEntity(String name, int number) {
this.name = name;
this.number = number;
}
@Override
public String toString() {
return "toString(): [name=" + name + ", number=" + number + "]";
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
the orderList-Component from Primefaces looks like that:
<p:orderList value="#{orderListBean.exampleList}"
var="exampleEntity" itemValue="#{exampleEntity}"
converter="orderListConverter">
<p:column style="width:25%">
#{exampleEntity.number}
</p:column>
<p:column style="width:75%;">
#{exampleEntity.name}
</p:column>
</p:orderList>
and the bean is implemented as follows:
@SessionScoped
@ManagedBean(name = "orderListBean")
public class OrderListBean {
private List<ExampleEntity> exampleList;
@PostConstruct
public void init() {
exampleList = new ArrayList<ExampleEntity>();
exampleList.add(new ExampleEntity("nameOne", 1));
exampleList.add(new ExampleEntity("nameTwo", 2));
exampleList.add(new ExampleEntity("nameThree", 3));
exampleList.add(new ExampleEntity("nameFour", 4));
exampleList.add(new ExampleEntity("nameFive", 5));
}
public List<ExampleEntity> getExampleList() {
return exampleList;
}
public void setExampleList(List<ExampleEntity> exampleList) {
this.exampleList = exampleList;
}
}
1) when debugging, the value
Parameter of getAsObject()
contains
the number
of the ExampleEntity
, but I had expected the
toString()
method of ExampleEntity
to be called!
2) What is the correct content for itemValue
attribute?
Is it a kind of convention over configuration? Or how does the component
'know', to use the whole object, when inserting exampleEntity
into itemValue
Hope everything is clear! Tanks a lot for any explanation!
Converters basically serve to transform values in 2 directions:
In your
getAsString
you established, that the string representation, the one which client uses, isexampleEntity
's number. So that's what gets rendered to client as a value. And later, when the client submits its value, that value isnumber
. To convert it to the object (server) representation, thegetAsObject
called with thenumber
as a parameter.The server can't possibly call
getAsObject
withexampleEntity.toString()
, because it doesn't have theexampleEntity
instance at that point, only the submittednumber
.To illustrate, this should hold:
getAsObject
andgetAsString
should be inversive in their input and output.To answer your 2nd question: that depends on your needs. You could say
itemValue="#{exampleEntity.number}"
, but that would make sense only if you're not interested in theexampleEntity
itself, i.e. on submit you would get thenumber
from the client and that's all you need for your server-side logic.