JSF2
This is version . It is not the current version, and thus it cannot be edited.
Back to current version   Restore this version

Hier sind einige Informationen über JSF 2 gespeichert.

Composite Tags#

AJAX Status#

Die Component zeit den AJAX-Status an.
<?xml version="1.0" encoding="UTF-8"?>
<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:c="http://java.sun.com/jsp/jstl/core"
	xmlns:cc="http://java.sun.com/jsf/composite"
>
	<cc:interface>
		<cc:attribute name="status" default="begin"/>
	</cc:interface>
	<cc:implementation>
		<script type="text/javascript">
			jsf.ajax.addOnEvent(function(data) {
				document.getElementById('#{cc.clientId}:status').style.visibility =
					data.status == '#{cc.attrs.status}' ? 'visible' : 'hidden';
			});
		</script>
		<div id="#{cc.clientId}:status" style="visibility: hidden;">
		    <cc:insertChildren/>
		</div>
	</cc:implementation>
</html>

Verwendung zum Beispiel wie folgt:

<test:ajaxStatus>
	<h:graphicImage value="/images/wait30trans.gif"/>
</test:ajaxStatus>

HTML Element Tag#

Der Tag rendert ein HTML-Element mit ClientId und übergibt alle Attribute und Childrens.
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:c="http://java.sun.com/jsp/jstl/core"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:cc="http://java.sun.com/jsf/composite"
>
	<cc:interface name="test">
		<cc:attribute name="element" required="true"/>
		<cc:attribute name="rendered"/>
	</cc:interface>
	<cc:implementation>
		<c:if test="#{!rendered or rendered}">
			<h:outputText value="&lt;#{cc.attrs.element} id=&quot;#{cc.clientId}&quot;" escape="false"/>
			<c:forEach items="#{cc.attributes}" var="attribute">
				<h:outputText value=" #{attribute.key}=&quot;#{attribute.value}&quot;" escape="false"
					rendered="#{!attribute.key.startsWith('javax.faces') and
						!attribute.key.startsWith('com.sun') and
						attribute.key != 'element' and
						attribute.key != 'rendered'}"/>
			</c:forEach>
			<h:outputText value="&gt;" escape="false"/>
			<cc:insertChildren/>
			<h:outputText value="&lt;/#{cc.attrs.element}&gt;" escape="false"/>
		</c:if>
	</cc:implementation>
</html>

Validierung prüfen#

FacesContext.getCurrentInstance().isValidationFailed();

#{facesContext.validationFailed}

Setup#

web.xml
	<context-param>
		<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
		<param-value>server</param-value>
	</context-param>
	<context-param>
		<param-name>javax.faces.PROJECT_STAGE</param-name>
		<param-value>Development</param-value>
	</context-param>
	<context-param>
		<param-name>javax.faces.FACELETS_LIBRARIES</param-name>
		<param-value>/WEB-INF/test.taglib.xml</param-value>
	</context-param>
	<context-param>
		<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
		<param-value>true</param-value>
	</context-param>
	
	<servlet>
		<servlet-name>Faces Servlet</servlet-name>
		<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>/faces/*</url-pattern>
	</servlet-mapping>

Der Eintrag javax.faces.FACELETS_SKIP_COMMENTS sorgt dafür, dass in XML-Kommentaren "<!-- Comment -->" keine EL-Expressions ausgewertet werden. Wird dieses Konfiguration nicht angegeben, kann es zu schwer auffindbaren Fehlern kommen.

EL-Expressions 2.2#

Die neuen EL-Expressions erlauben das Binding an Action-Methods, die Parameter besitzen:
<h:commandButton value="Test" action="#{test.action('param')}"/>

In der pom.xml die Libs referenzieren:

		<dependency>
			<groupId>javax.el</groupId>
			<artifactId>el-api</artifactId>
			<version>2.2</version>
		</dependency>
		<dependency>
			<groupId>org.glassfish.web</groupId>
			<artifactId>el-impl</artifactId>
			<version>2.2</version>
		</dependency>
		
		<repository>
			<id>maven.java.net</id>
			<name>Java.net Maven2 Repository</name>
			<url>http://download.java.net/maven/2</url>
		</repository>

Und in der web.xml die Factory festlegen:

	<context-param>
		<param-name>com.sun.faces.expressionFactory</param-name>
		<param-value>com.sun.el.ExpressionFactoryImpl</param-value>
	</context-param>

In Google Application Engine klappt das nicht, dort kann nur JBoss EL verwendet werden.

Debugging#

Debug Page#

Die Debug-Page von Facelets öffnet sich bei einer Exception. Sie kann aber auch manuell geöffnet werden, dies ist nützlich um die Bean-Scopes zu untersuchen oder den Component-Tree. Dazu einfach das Tag einfügen:
<ui:debug hotkey="q"/>

Das Hotkey arbeitet in diesem Fall mit CTRL+SHIFT+Q. Falls das Hotkey nicht funktioniert, ist es wahrscheinlich durch etwas anderes abgefangen und man ersetzt es durch ein anderes.

Gelbe Messages#

Werden gelbe Warnings wie z.B. "The form component needs to have a UIForm in its ancestry. Suggestion: enclose the necessary components within <h:form>" beim Rendern einer Seite unten angezeigt, können diese gefunden werden, indem ein Breakpoint bei MessageUtils.getExceptionMessage(String messageId, Object... params) gesetzt wird.

Rote Messages#

Wenn Messages der Art "Warning: This page calls for XML namespace declared with prefix div but no taglibrary exists for that namespace." auftauchen, liegt es an fehlenden Namespace-Definitionen der entsprechenden Seite. In großen Projekten mit verschachtelten Includes können diese schwer zu finden sein. Die Fehlermeldung selbst wird in der Class com.sun.faces.facelets.tag.CompositeTagLibrary erzeugt, hier kann ein Breakpoint gesetzt werden.

Annotation Processing#

In den meisten Servlet-Containern werden die JSF-Annotations automatisch verarbeitet, wie @ManagedBean, @SessionScoped und so weiter. Allerdings klappt das nicht immer, wie Beispielsweise bei embedded Tomcat. Dann kann mit folgendem Servlet-Context-Parameter abgeholfen werden:
	<context-param>
		<param-name>com.sun.faces.injectionProvider</param-name>
		<param-value>com.sun.faces.vendor.WebContainerInjectionProvider</param-value>
	</context-param>

Tag-Handler#

In JSF 2 werden Tag-Handler bentutzt, um die Tags zu erzeugen. Diese werden von javax.faces.view.facelets.TagHandler abgeleitet. Die beiden wichtigsten Fälle sind:

Component Tree#

Wenn eine Komponente nicht im Component-Tree erscheint, kann mit folgendem Konstrukt im Handler abgeholfen werden:
	@Override
	public void onComponentCreated(FaceletContext context, UIComponent component, UIComponent parent) {
		parent.getChildren().add(component);
	}

Ein interessanter Artikel dazu.

JSF AJAX-Push#

Momentan relativ einfach zu konfigurieren ist der Primefaces-Push, der seit der Version 3.4 auf Atmosphere-Framework basiert. Atmosphere-Framework ist momentan das führende Framework für alle möglichen Push-Varianten, zwischen Server und Browser, falls man sich nicht vollzeit mit diesem Thema beschäftigen möchte.

pom.xml:

		<dependency>
			<groupId>org.primefaces</groupId>
			<artifactId>primefaces</artifactId>
			<version>3.4-SNAPSHOT</version>
		</dependency>
	...

	<repositories>
		<repository>
			<id>prime-repo</id>
			<name>Prime Technology Maven Repository</name>
			<url>http://repository.primefaces.org</url>
			<layout>default</layout>
		</repository>
	</repositories>

web.xml, es ist eine Web-App 3.0 erforderlich:

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
      version="3.0"> 
        ...
	<servlet>
		<servlet-name>Push Servlet</servlet-name>
		<servlet-class>org.primefaces.push.PushServlet</servlet-class>
		<async-supported>true</async-supported>
	</servlet>
	<servlet-mapping>
		<servlet-name>Push Servlet</servlet-name>
		<url-pattern>/primepush/*</url-pattern>
	</servlet-mapping>
	...
</web-app>

Java:

    public void someMethod() {
	PushContextFactory.getDefault().getPushContext().push("/test", null);
    }

Der Eintrag "/test" ist der sogenannte Channel über dem gepusht wird.

Im XHTML wird entweder ein AJAX-Tag verwendet:

	<p:socket channel="/test" autoConnect="true">
		<p:ajax event="message" update=":push-form:chat"/>
	</p:socket>

Oder wenn der Update manuell gemacht werden soll, kann auch Javascript verwendet werden:

	<p:socket channel="/test" autoConnect="true" onMessage="someMethod"/>

Die Methode wird dann mit einem Parameter "data" aufgerufen, welches dem JSON-Serialisiertem Objekt aus dem Server-Push-Aufruf context.push("/test", data); entspricht.

FacesContext manuell erzeugen#

Innerhalb eines Servlet-Auftrufs kann der Kontext einfach erzeugt werden:
FacesContextFactory factory = (FacesContextFactory)FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
Lifecycle lifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
factory.getFacesContext(servletContext, request, response, lifecycle);

Außerhalb von Servlets braucht man den ServletContext, HttpServletRequest und HttpServletResponse, der nicht ganz einfach zu implementieren ist.