Objekt aus JSF Custom Validator erhalten

Eine Dropdown-Liste in Form eines f:selectItems-Tags in JSF 2.2 kann einzelne Einträge nur in Form von Strings zurückgeben. Möchte man aber ein Objekt von einem Eintrag aus der Dropdown-Liste haben, so muss man einen JSF Converter implementieren.

Bei Verwendung eines Converters wird für jeden Eintrag aus der Dropdown-Liste die getAsString-Methode ausgeführt, welche das gebundene Objekt Objekt als Parameter erhält. Das gebundene Objekt kann dann zusammen mit einem Key über den FacesContext in der Session gespeichert werden.

Bei der Auswahl eines Elements im Dropdown-Element wird dann die getAsObject-Methode des Convertes aufgerufen. Die getAsObject-Methode enthält entgegen der getAsString-Methode nicht das direkte Objekt sondern nur den Key, den die getAsString zurückgibt. Der erhaltene Key kann aber genutzt werden, um das Objekt wieder aus der Session zu lesen. Der folgende Code zeigt diesen Ansatz:

XHTML

1
2
3
4
5
6
7
8
9
<h:selectOneMenu value="#{playlistController.item.category}">
  <f:converter converterId="CategoryConverter" />
  <f:selectItems 
    value="#{categoryController.items}" 
    var="item"
    itemValue="#{item}" 
    itemLabel="#{item.name}" 
    />
</h:selectOneMenu>

CategoryConverter.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package de.fhb.converter;
 
import de.fhb.entities.Category;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
 
@FacesConverter("CategoryConverter")
public class CategoryConverter implements Converter {
 
  @Override
  public String getAsString(FacesContext context, UIComponent component, Object value) {
    Category item = (Category) value;
    String key = CategoryConverter.class.getName() + item.getId();
    context.getExternalContext().getSessionMap().put(key, item);
    System.out.println("Key: " + key);
    return key;
  }
 
  @Override
  public Object getAsObject(FacesContext context, UIComponent component, String value) {
    Category item = (Category) context.getExternalContext().getSessionMap().get(value);
    System.out.println("Value: " + item.getName());
    return item;
  }
}

Achtung: Der Ansatz komplette Dropdown-Listen in der Session zu speichern ist nicht elegant, da die Session auf Client- und Server-Seite sehr speicherintensiv werden kann. Mir ist jedoch keine bessere Variante als die hier Vorgestellte bekannt. Alternativ wäre der Einsatz von SelectItemsConverter aus der OmniFaces-Bibliothek denkbar. Dadurch wird aber die Abhängigkeit zu einer 3rd-Party-Bibliothek erhöht.

Wichtig: Damit die Speicherung von Objekten aus einem Dropdown-Element funktioniert, muss die Klasse des entsprechenden Objekts die equals-Methode sinnvoll überschreiben. Beim Mapping der Objekte in Werte für das Dropdown-Menü werden nämlich Kopien erzeugt, welche dann beim Rücktransfer nicht mehr mit den ursprünglichen Objekten identisch sind. Es muss daher eine equals-Methode implementiert werden, die beide Objekte (die Dropdown-Kopie als auch das Original) wieder als eins erkennt.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.