ajeh
ajeh

Reputation: 2784

Confused with PrimeFaces Converter (as it applies to selectOneMenu)

The implementation of PlayersConverter in AutoComplete demo actually serves not only as a converter, but also as a loader for Players list. I am a bit weary of this model, as loading is already implemented in my project. I don't understand why Converter interface was not implemented as template:

Converter<Players>

instead.

Yes, these demos look great, but seeing data being statically loaded into the lists inside the converters I can't figure how to use that in real life application, where converter should not really have anything to do with data loading.

Is it at all possible to use PrimeFaces converters without actually loading data in them? How can I inform a converter of the type of list item it is supposed to convert?

Upvotes: 4

Views: 3524

Answers (1)

BalusC
BalusC

Reputation: 1108642

I understand that you're talking about PlayerConverter as shown in this page. This is just an extremely localized implementation for pure demonstration purposes (the showcase isn't using any DB and they have to get hold of those data somewhere). This is indeed confusing and misleading. In real world code, you should be interacting with the data from the database, something like follows:

@ManagedBean
public class PlayerConverter implements Converter {

    @EJB
    private PlayerService service;

    public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) {
        if (submittedValue == null || submittedValue.isEmpty()) {
            return null;
        }

        try {
            return service.find(Integer.valueOf(submittedValue));
        } catch (NumberFormatException exception) {
            throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Conversion Error", "Not a valid player ID"));
        }
    }

    public String getAsString(FacesContext context, UIComponent component, Object modelValue) {
        if (modelValue == null) {
            return "";
        }

        if (modelValue instanceof Player) {
            return String.valueOf(((Player) modelValue).getNumber());
        } else {
            throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Conversion Error", "Not a valid player instance"));
        }
    }
}

From your original question before the edit:

Further, when they write in their demos converter="player" what does "player" refer to?

As to the converter="player", it's just the value of the <converter-id> as registered in faces-config.xml. You can also register it via @FacesConverter annotation:

@FacesConverter("player") // I'd rather rename it to playerConverter.
public class PlayerConverter implements Converter {
    // ...
}

Note that my example uses @ManagedBean instead, otherwise using @EJB would not have been possible. See also How to inject @EJB, @PersistenceContext, @Inject, @Autowired, etc in @FacesConverter?


Unrelated to the concrete problem, I understand that the whole converter seems some kind of unnecessary code duplication. The JSF utility library OmniFaces has identified and solved this problem in flavor of omnifaces.ListConverter. Just use converter="omnifaces.ListConverter" instead of converter="player" and the whole converter class. Note that there's a similar converter for components using <f:selectItem(s)>, the omnifaces.SelectItemsConverter.

Upvotes: 4

Related Questions