问题
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!
回答1:
Converters basically serve to transform values in 2 directions:
- Server to client, when the value is rendered.
- Client to server, when the value is submitted.
In your getAsString
you established, that the string representation, the one which client uses, is exampleEntity
's number. So that's what gets rendered to client as a value. And later, when the client submits its value, that value is number
. To convert it to the object (server) representation, the getAsObject
called with the number
as a parameter.
The server can't possibly call getAsObject
with exampleEntity.toString()
, because it doesn't have the exampleEntity
instance at that point, only the submitted number
.
To illustrate, this should hold:
obj.equals(conv.getAsObject(ctx, comp, conv.getAsString(ctx, comp, obj)));
getAsObject
and getAsString
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 the exampleEntity
itself, i.e. on submit you would get the number
from the client and that's all you need for your server-side logic.
回答2:
@FacesConverter(value = "EntityConverter")
public class EntityConverter implements Converter, Serializable {
private static final long serialVersionUID = 1L;
public EntityConverter() {
super();
}
@Override
public Object getAsObject(final FacesContext context, final UIComponent component, final String value) {
if (value == null) {
return null;
}
return fromSelect(component, value);
}
/**
* @param currentcomponent
* @param objectString
* @return the Object
*/
private Object fromSelect(final UIComponent currentcomponent, final String objectString) {
if (currentcomponent.getClass() == UISelectItem.class) {
final UISelectItem item = (UISelectItem) currentcomponent;
final Object value = item.getValue();
if (objectString.equals(serialize(value))) {
return value;
}
}
if (currentcomponent.getClass() == UISelectItems.class) {
final UISelectItems items = (UISelectItems) currentcomponent;
final List<Object> elements = (List<Object>) items.getValue();
for (final Object element : elements) {
if (objectString.equals(serialize(element))) {
return element;
}
}
}
if (!currentcomponent.getChildren().isEmpty()) {
for (final UIComponent component : currentcomponent.getChildren()) {
final Object result = fromSelect(component, objectString);
if (result != null) {
return result;
}
}
}
if (currentcomponent instanceof OrderList) {
Object items = ((OrderList) currentcomponent).getValue();
List<Object> elements = (List<Object>) items;
for (final Object element : elements) {
if (objectString.equals(serialize(element))) {
return element;
}
}
}
return null;
}
/**
* @param object
* @return the String
*/
private String serialize(final Object object) {
if (object == null) {
return null;
}
return object.getClass() + "@" + object.hashCode();
}
@Override
public String getAsString(final FacesContext arg0, final UIComponent arg1, final Object object) {
return serialize(object);
}
}
回答3:
Prueba con uno genérico para los orderList. Este funciona a la perfección.
@Override
public Object getAsObject(final FacesContext context, final UIComponent component, final String value) {
if (value == null) {
return null;
}
return fromSelect(component, value);
}
private Object fromSelect(final UIComponent currentcomponent, final String objectString) {
if (currentcomponent instanceof OrderList) {
final Object items = ((OrderList) currentcomponent).getValue();
final List<Object> elements = (List<Object>) items;
for (final Object element : elements) {
if (objectString.equals(serialize(element))) {
return element;
}
}
}
return null;
}
private String serialize(final Object object) {
if (object == null) {
return null;
}
return object.getClass() + "@" + object.hashCode();
}
@Override
public String getAsString(final FacesContext arg0, final UIComponent arg1, final Object object) {
return serialize(object);
}
来源:https://stackoverflow.com/questions/30523944/porderlist-converter-getasobject-doesnt-call-object-tostring