I wrote a simple custom component with JSF1 and it works fine.
But when I use it in JSF2, it doesn’t work. Here is how I use it:
<?xml version="1.0" encoding="UTF-8"?>
<!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:d="http://jsftutorials.com/"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:body>
<f:view>
<d:ticker>Hello World!</d:ticker>
</f:view>
</h:body>
</html>
Here is how the component is created for JSF1:
faces-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<faces-config 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-facesconfig_2_0.xsd"
version="2.0">
<component>
<component-type>ticker</component-type>
<component-class>ticker.UITicker</component-class>
</component>
</faces-config>
ticker.tld
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
"http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
<tlib-version>1.0</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>d</short-name>
<uri>http://jsftutorials.com/</uri>
<tag>
<name>ticker</name>
<tag-class>ticker.TickerTag</tag-class>
<body-content>JSP</body-content>
</tag>
</taglib>
TickerTag.java
package ticker;
import javax.faces.component.UIComponent;
import javax.faces.webapp.UIComponentTag;
@SuppressWarnings("deprecation")
public class TickerTag extends UIComponentTag {
public void release() {
super.release();
}
protected void setProperties(UIComponent component) {
super.setProperties(component);
}
public String getComponentType() {
return "ticker";
}
public String getRendererType() {
return null;
}
}
UITicker.java
package ticker;
import java.io.IOException;
import javax.faces.component.UIOutput;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
public class UITicker extends UIOutput {
public void encodeBegin(FacesContext context) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.startElement("div", this);
}
public void encodeEnd(FacesContext context) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.endElement("div");
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name></display-name>
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<context-param>
<param-name>javax.faces.CONFIG_FILES</param-name>
<param-value>/WEB-INF/faces-config.xml</param-value>
</context-param>
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
<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>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
</web-app>
What should I change to get it to work in JSF2?
That’s a JSP tag. JSP is deprecated in JSF 2.0 and succeeded by Facelets (XHTML). You’re indeed using Facelets instead of JSP. Your component would only work when you’re using JSF2 with legacy JSP instead of Facelets. You need to change the old JSP tag to be a Facelets tag.
Here are the changes you need to make:
faces-config.xml: remove the<component>altogether.ticker.tld: rename it toticker.taglib.xmland replace the content by:TickerTag.java: remove it altogher. You don’t need it for Facelets.UITicker.java: add the following annotation on the class (this replaces the<component>entry infaces-config.xml)(note: the annotation value must match
<component-type>in the taglib XML file, not<tag-name>)As
UIOutputdoes by default not allow text children, it’s basically the wrong choice to represent a<div>component. You’d better extendUIPanelinstead.(note that the standard
<h:panelGroup layout="block">component already renders a<div>like that; I understand that you’re just learning JSF, but just to be sure for the case you are really looking for a JSF component which renders a div)web.xml: add the following context param:(note: this is unnecessary when you provide the taglib as JAR file in
/WEB-INF/liband have the.taglib.xmlfile in/META-INFof the JAR)When reading/learning something about JSF, assure that you’re reading the right tutorials/resources targeted at JSF2 and not the ones targeted at JSF1. Many, many things are done differently.
See also: