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.

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.