4

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?

ajeh
  • 2,372
  • 2
  • 28
  • 52

1 Answers1

4

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.

Community
  • 1
  • 1
BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
  • I deleted the last part of the question just moments ago as I figured that FacesConverter annotation fixed that part. It's nowhere mentioned among the self-praises of PrimeFaces alluding to how easy to use it is. You are absolutely right as to the rest of points - writing converter for each of the list class items is exactly that - going back to writing redundant boilerplate code. – ajeh Sep 17 '13 at 16:09
  • I added omnifaces jar to the compile time libraries in NetBeans, included xmlns:of="http://omnifaces.org/functions" into html tag and supplied converter="omnifaces.SelectItemsConverter" to the p:selectListBox. The namespace has a warning that it is not used and the list box stopped working. What am I missing? – ajeh Sep 17 '13 at 16:37
  • Like as PrimeFaces and all other libraries, you need to install OmniFaces as well. See also https://code.google.com/p/omnifaces/. By the way, the converters doesn't require a XML namespace. Only the `` components/taghandlers and `#{of:xxx()}` functions do. – BalusC Sep 17 '13 at 16:38
  • It was added to the lib path as a jar. – ajeh Sep 17 '13 at 16:39
  • Wait, are you using `omnifaces.SelectItemsConverter` on ``? You should be using `omnifaces.ListConverter` as stated in the answer and showcase. – BalusC Sep 17 '13 at 16:41
  • No, it's all right - I just forgot to undo the changes made to use PF converter. It just worked on the selects without any issues. It's almost working for the list view (only once and assigns to a wrong select, but that's my code and I just need to figure it out). – ajeh Sep 17 '13 at 16:58