p:orderList converter getAsObject() doesn't ca

2019-07-26 22:24发布

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条回答
萌系小妹纸
2楼-- · 2019-07-26 23:00

Converters basically serve to transform values in 2 directions:

  1. Server to client, when the value is rendered.
  2. 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.

查看更多
登录 后发表回答