Creación de un componente en JSF2.
0. Índice de contenidos.
- 1. Introducción.
- 2. Entorno.
- 3. Creación de la clase java, el taglib y la vista.
- 4. Añadir un parámetro al componente..
- 5. Referencias.
- 6. Conclusiones.
1. Introducción
Ya vimos hace un tiempo en un tutorial de Alejandro https://adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=jsfComponent como crear un componente en JSF. Aunque ahora mismo existen muchas librerias de componentes, en ocasiones podrían no ofrecernos el componente que necesitamos y podríamos tener la necesidad de crearlo nosotros.
En este tutorial crearemos un componente personalizado con JSF 2 que básicamente realizará las funciones de un h:outputLabel. Primero crearemos las clases de java, el taglib y la vista y luego le añadiremos el parametro al componente.
2. Entorno.
El tutorial está escrito usando el siguiente entorno:
- Hardware: MacBookPro8,2 (2 GHz Intel Core i7, 4GB DDR3 SDRAM).
- AMD Radeon HD 6490M 256MB.
- Sistema Operativo: Mac OS X Snow Leopard 10.6.7.
- Eclipse Helios
3. Creación de la clase java, el taglib y la vista
.
Para este ejemplo todo lo que necesitaremos será una clase de java para nuestro componente, que tendrá la funcionalidad. Y un archivo xml que será el descriptor de la libreria de tags.
No tenemos necesidad de crear una clase Renderer para nuestro componente. En el ejemplo el código que se encargará de renderizar estará dentro de la clase de java.
El código de la clase java sería el siguiente:
package com.autentia.jsf.showcase.component; import java.io.IOException; import javax.faces.component.FacesComponent; import javax.faces.component.UIComponentBase; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; @FacesComponent(value = "HtmlCustomComponent") public class HtmlCustomComponent extends UIComponentBase { @Override public String getFamily() { return null; } @Override public void encodeAll(FacesContext context) throws IOException { final ResponseWriter writer = context.getResponseWriter(); writer.startElement("div", this); writer.writeAttribute("style", "color : red", null); writer.writeText("Hola adictosaltrabajo, hoy es: " + new java.util.Date(), null); writer.endElement("div"); } }
El nombre de la clase empieza por Html por convención, ya que el componente esta hecho para visualizarse en html por defecto. En el método encodeAll tenemos el código para que el componente se visualice en el cliente. La creacíon del html se realiza con un ResponseWriter que podemos recoger del contexto. Esta clase tiene varios métodos para escribir lenguaje de marcado entre ellos los que estamos utilizando aquí.
El método getFamily() devuelve la categoría general a la que pertenece el componente. Esto se utiliza para combinarlo con el rendererType para elegir un Renderer apropiado. En nuestro caso al no crear una familia de componentes ni de renderers podemos devolver null.
Y por último la anotacion @FacesComponent, que sería una alternativa a escribir el siguiente código en el faces-config.xml:
<component> <component-type>HtmlCustomComponent</component-type> <component-class>com.autentia.jsf.showcase.component.HtmlCustomComponent</component-class></component>
Lo que hacemos con esto es registrar el componente para que en tiempo de ejecución se pueda construir.
Por último vamos a crear una tag library de Facelet para poder utilizar el componente en una vista.
<?xml version='1.0' encoding='UTF-8'?> <facelet-taglib 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-facelettaglibrary_2_0.xsd" version="2.0"> <namespace>http://autentia.com/tutoriales</namespace> <tag> <tag-name>customComponent</tag-name> <component> <component-type>HtmlCustomComponent</component-type> </component> </tag> </facelet-taglib>
Colocamos el taglib en WEB-INF/classes/META-INF/ para que la aplicación sea capaz de encontrarlo en tiempo de ejecución. Para que sea capaz de encontrarlo, el archivo debe acabar en .taglib.xml, en nuestro caso, custom.taglib.xml
Para usar el componente basta con crear un xhtml:
<!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:h="http://java.sun.com/jsf/html" xmlns:aut="http://autentia.com/tutoriales"> <h:head> <title>Componente personalizado JSF 2.</title> </h:head> <h:body> <aut:customComponent /> </h:body> </html>
La URI del taglib debe ser la misma que hemos puesto en nuestro fichero xml, y como nuestro componente no necesita ningún atributo, con poner <aut:customComponent /> nos bastaría.
4. Añadir un parámetro al componente.
Una vez que ya tenemos nuestro componente creado, podría ser interesante que tuviera un parámetro de entrada para poder recibir el texto que queremos visualizar.
Cualquier atributo que se añada en la vista es accesible en nuestra clase java a través del mapa que devuelve getAttributes(). Vamos a añadir un atributo custommsg en nuestro .xhtml y cambiaremos el metodo encodeAll() para que escriba lo que haya en ese atributo.
... @Override public void encodeAll(FacesContext context) throws IOException { final ResponseWriter writer = context.getResponseWriter(); writer.startElement("div", this); writer.writeAttribute("style", "color : red", null); final String message = (String) this.getAttributes().get("custommsg"); if (null == message) { writer.writeText("Hola adictosaltrabajo, hoy es: " + new java.util.Date(), null); } else { writer.writeText(message, null); } writer.endElement("div"); } ...
Ahora podemos utilizar <aut:customComponent custommsg=»Mensaje pasado como parametro en el xhtml» /> y veremos este mensaje en el navegador.
Facelets soporta automáticamente EL, así que si escribimos como atributo <aut:customComponent custommsg=»#{param.msg}» />. Con esto podríamos pasar el parámetro msg en la URL y se visualizaría en la página. Por ejemplo si accedemos a la url añadiendole: ?msg=Hola%20desde%20la%20url veremos «Hola desde la url» en nuestro navegador.
5. Referencias.
6. Conclusiones.
Con este tutorial hemos podido ver lo básico para crear un componente en JSF 2. Algo que puede resultarnos útil si tenemos la necesidad de usar un componente que no existe en una librería de componentes.
Espero que os haya resultado útil. Cualquier duda, comentario o sugerencia podéis hacerla a continuación.
Un saludo.
César López.
Muchas gracias Cesar por un ejemplo tan práctico como este que, aunque pueda parecer muy básico, para la gente que empieza a crear componentes JSF es perfecto para comprender los pasos que hay que dar.
Creo que faltaría incluir en este tutorial que hay que registrar el archivo taglib en web.xml para que Eclipse no muestre un warning xmlns:aut=\\\»http://autentia.com/tutoriales\\\» y poder utilizar la etiqueta sin problemas (por lo menos es lo que yo he tenido que realizar para que me funcionase correctamente el componente).
facelets.LIBRARIES
/WEB-INF/classes/META-INF/custom.taglib.xml
Enhorabuena y muchas gracias por la aportación que está haciendo la gente de Autentia a la comunidad de desarrolladores.
Efectivamente Hay que registrar dicho componente en el WEB.xml:
facelets.LIBRARIES
/WEB-INF/HtmlCustomComponent.taglib.xml
Hola, tenía una pregunta, gracias de antemano.
El prefijo aut, ¿dónde lo das de alta?
Vale, ya vi que se define en la cabecera: xmlns:aut=\\\»http://autentia.com/tutoriales\\\»
Si quisiese que mi custom component tuviese hijos, es decir:
Como podría hacerlo?