10/29/2010

Die eigene JSF Komponente (incl Bean - Verweis) unter JSF 1.2

Hier eine kleine Anleitung, wie man seine eigene JSF - Komponente baut, und diese so gestaltet, daß sie mit verschiedenen Beans wiederverwenderbar ist. Nicht ganz so komfortabel wie die custom components bei JSF 2.0, aber es lassen sich fast die gleichen Ergebnisse erzielen.

1) Referenz auf die zu erstellende TagLib erstellen:

Den folgenden Eintrag der web.xml hinzufügen:


<context-param>
<param-name>facelets.LIBRARIES</param-name>
<param-value>/ui/templates/taglib.xml</param-value>
</context-param>
Damit ist eure Taglib JSF bekannt gemacht.

2) Die TabLib mit Verweisen zu den einzelnen Files füllen:

Hier ein Beispieleintrag in der taglib (liegt unter /ui/templates/taglib.xml), die auf eine Komponente verweist:
<?xml version="1.0"?>
<!DOCTYPE facelet-taglib PUBLIC
  "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
  "facelet-taglib_1_0.dtd">
<facelet-taglib>
<namespace>http://some.namespace.com</namespace>
<tag>
<tag-name>beanComponent</tag-name>
<source>beanComponent.xhtml</source>
</tag>
</facelet-taglib>

Über den angegebenen namespace (some.namespace.com) könnt ihr später von euren referenzierenden Files auf eure Komponenten zugreifen. Der Zugriff erfolgt über den tag namen (hier: beanComponent).

3) Aufruf der Komponente

Für den Aufruf innerhalb einer facelets Datei, fügt den namespace zu den referenzierten namespaces im header hinzu:
xmlns:some="http://some.namespace.com"
Auch das geht unter JSF 2.0 einfacher ... anyway ... der Zugriff kann nun folgendermaßen erfolgen:

<some:beanComponent bean=${backingbean}/>

In diesem Beispiel übergeben wir eine komplette Referenz auf eine JSF backing bean an unsere Komponente. Egal wie wir die Komponente dort nutzen wollen, wichtig ist, daß die Referenz nicht wie bei Standard - JSF üblich mittels #{backingbean} sondern über den JSTL Ausdruck ${} erfolgt.

4) Die Komponente

Die Komponente enthält zuerst einmal alle üblichen Referenzen, startet dann ein ui:composition, alles wie immer, und greift dann auf Methoden in der Bean zu:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:z="http://www.qualcomm.com/jsf/core"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:fn="http://java.sun.com/jsp/jstl/functions">
<ui:composition>
<h:outputText value="#{backingBean.wert}"/>
</ui:composition>
</html>


Die Bean kann somit ganz einfach (wie immer) über #{backingBean.wert} angesprochen werden. Das ermöglicht es, dieselbe Komponente mit verschiedenen Beans anzusprechen.
Damit könnte dann ein dokumenten browser oder ähnliches erstellt werden.

5) Erweiterung

Sollen nicht nur die Beans sondern auch die Methoden - Namen dynamisch sein, so kann der Methodenname als eigener Parameter übergeben werden:

<some:beanComponent bean=${backingbean} method="wert"/>
Der Zugriff erfolgt dann folgendermaßen:
<h:outputText value="#{backingBean[method]}"/>

Zu empfehlen ist das jedoch nicht - die Coupling steigt und die Wartbarkeit sinkt.