Creación de un portlet con Primefaces
0. Índice de
contenidos.
- 1. Entorno
- 2. Introducción
- 3. Creando el proyecto
- 4. Añadiendo la dependencia de primefaces
- 5. Configurando portlet.xml
- 6. Configurando web.xml
- 7. Configurando faces-config.xml
- 8. Configurando ficheros liferay-portlet.xml y liferay-display.xml
- 9. Desarrollando el portlet
- 10. Probando el resultado
- 11. Conclusiones
1. Entorno
Este tutorial está escrito usando el siguiente entorno:
- Hardware: Portátil Mac Book Pro 17″ (2,6 Ghz Intel Core
i7, 8 GB
DDR3) - Sistema Operativo: Mac OS X Snow Leopard 10.6.4
- Spring MVC Portlet 3.0.4
- Maven 2.2.1
- Eclipse 3.6 (Helios) con M2Eclipse
- Liferay 6.0.5
- Primefaces 2.2.1
2. Introducción
En este tutorial vamos a ver como configurar nuestro proyecto de Liferay para hacer uso de las características de JSF 2.0 a través de la librería Primefaces, este enlace tenéis una introducción a esta librería.
Aquí nos vamos a centrar en la configuración necesaria y vamos a ver un ejemplo muy simple para saber que todo ha ido bien.
3. Creando el proyecto
Para crear el proyecto tenemos que seguir los mismos pasos que encontramos en este otro tutorial: Ejemplo básico con Spring MVC Portlet.
Lo único que va a cambiar (si queréis) es el nombre del artifactId, el cual vamos a llamar liferay-primefaces.
4. Añadiendo la dependencia de primefaces
Para añadir la dependencia de primefaces a nuestro proyecto tenemos que editar el fichero pom.xml y añadir las siguientes dependencias a las existentes:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
javax.faces jsf-api 2.0 com.sun.faces jsf-impl 2.0.4-b09 org.primefaces primefaces 2.2 org.portletfaces portletfaces-bridge 2.0.0-BETA3 javax.servlet.jsp jsp-api 2.0 provided |
Si tenéis algún problema al descargar estas depedendencia probar a añadir los siguientes repositorios en vuestro pom.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
maven2-repository.dev.java.net http://download.java.net/maven/2 maven2-repository.jboss.org http://repository.jboss.org/maven2 maven2-repository-portletfaces.org prime-repo Prime Technology Maven Repository http://repository.prime.com.tr default |
5. Configurando portlet.xml
Como ya sabéis, si habéis seguido otros tutoriales anteriores sobre portlets, el fichero portlet.xml es el más importante en los proyectos de estas características, dado que es aquí donde se definen los portlets que va a tener nuestro proyecto y las vistas y clases que lo van a implementar. En este caso vamos a definir un único portlet con las vistas VIEW y EDIT. A destacar que para utilizar las características JSF 2.0 de primefaces, la clase de nuestro portlet tiene que ser org.portletfaces.bridge.GenericFacesPortlet.
Aquí se muestra el contenido del fichero pom.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
1 PrimeFaces Portlet org.portletfaces.bridge.GenericFacesPortlet javax.portlet.faces.defaultViewId.view /view.xhtml javax.portlet.faces.defaultViewId.edit /edit.xhtml text/html view edit PrimeFaces Portlet PrimeFaces Portlet JSF 2.0 |
6. Configurando web.xml
El siguiente paso a dar es configurar el fichero web.xml donde vamos a definir el servlet que se va a encargar de gestionar las peticiones que tengan que entrar por el ciclo de vida de JSF 2.0. Este sería el contenido resultante:
1 2 3 |
Faces Servlet javax.faces.webapp.FacesServlet 1 |
7. Configurando faces-config.xml
Todo el que alguna vez haya trabajado con JSF sabrá que este es un fichero muy importante, pero a partir de la versión 2.0 se ha convertido en un fichero opcional dado que todo se puede definir con anotaciones. El caso es que el bridge que utiliza nuestro portlet requiere de este fichero aunque no contenga nada, si no existe nos lanzará un error . Aquí os dejo un ejemplo de contenido:
1 |
8. Configurando ficheros liferay-portlet.xml y liferay-display.xml
Ya sabemos que estos ficheros son exclusivos de Liferay y que se utilizan para definir características del portlet que sólo son relevantes para Liferay como: en que categoría situar el portlet, si va a ser instanciable, como va a gestionar los permisos, etc …
Aquí os propongo unos ejemplos para el contenido de estos ficheros:
liferay-portlet.xml
1 2 3 |
1 true false |
liferay-display.xml
1 |
<portlet id="1" /> |
9. Desarrollando el portlet
Hasta aquí ya tenemos el proyecto configurado para poder comenzar a desarrollar nuestro portlet JSF 2.0 con la librería de Primefaces. Este ejemplo está basado en el portlet de ejemplo que la gente de Primefaces describe en su documentación oficial. Es que mi fuerte no es la imaginación 😉
El primer paso va a ser la implementación de una página de bienvenida a nuestro porlet, la cual la vamos a desarrollar en el fichero /view.xhtml, definido en el portlet.xml, con el siguiente contenido:
1 |
<div>Welcome to Gambit Portlet Powered by PrimeFaces</div> |
Como veis simplemente muestra en texto en el modo VIEW del portlet. Ahora vamos a implementar la funcionalidad del portlet en el modo EDIT para lo cual vamos a editar el fichero /edit.xhtml con el siguiente contenido:
1 2 3 4 5 6 7 8 |
<p:messages id="messages" /> <h:outputText value="Total Amount: " /> <h:outputText value="#{gambitController.amount}" /> <h:outputText value="Bet:" /> <h:inputText value="#{gambitController.bet}" /> <p:commandButton value="RED" actionListener="#{gambitController.playRed}" update="@parent" /> <p:commandButton value="BLACK" actionListener="#{gambitController.playBlack}" update="@parent" /> |
En este ejemplo vamos a implementar un juego de apuestas. En primer lugar se muestra el total obtenido después de cada tirada, luego el usuario puede introducir la cantidad que desea apostar y a que color entre rojo o negro.
Por último vamos a implementar la funcionalidad del juego en un ManagedBean que va a actuar de controlador con el siguiente contenido:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
package com.autentia.primeportlet; import java.io.Serializable; import javax.faces.application.FacesMessage; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; import javax.faces.context.FacesContext; @ManagedBean(name="gambitController") @SessionScoped public class GambitController implements Serializable { private int amount = 10000; private int bet; public int getBet() { return bet; } public void setBet(int bet) { this.bet = bet; } public int getAmount() { return amount; } public void playRed() { play(0); } public void playBlack() { play(1); } private void play(int winCondition) { int result = (int) (Math.random() * 2); FacesMessage msg = new FacesMessage(); if(result == winCondition) { amount = amount + bet; msg.setSummary("YOU WIN!!!"); msg.setSeverity(FacesMessage.SEVERITY_INFO); } else { amount = amount - bet; msg.setSummary("YOU LOST!!!"); msg.setSeverity(FacesMessage.SEVERITY_ERROR); } FacesContext.getCurrentInstance().addMessage(null, msg); } } |
En esta clase, definida como ManagedBean con anotaciones de ahí que no haya que editar el fichero faces-config.xml, definimos los atributos y la lógica del juego, mostrando un mensaje dentro del portlet indicando si el usuario a ganado o perdido la apuesta.
10. Probando el resultado
Para probar el resultado lo único que tenemos que hacer en un package de nuestro proyecto ejecutando mvn clean package en el terminal, seguido de mvn liferay:deploy. Muy importante no olvidar modificar la propiedad de nuestro pom.xml apuntando a la carpeta deploy del servidor de Liferay que queramos utilizar para la prueba.
Esto desplegará nuestro portlet en Liferay y podremos instanciarlo en cualquier página con lo que veríamos lo siguiente:
Con los permisos necesarios, por ejemplo, logándonos con Bruno, podríamos a acceder a las preferencias del portlet como se muestra en la imagen:
Con lo que deberíamos ver algo como esto:
En este punto ya podemos jugarnos el dinero apostando al rojo o al negro. En caso de ganar se mostraría de esta forma:
Y en caso de perder:
11. Conclusiones
Como veis crear un portlet utilizando la última versión de JSF no es nada complicado, gracias al bridge GenericFacesPortlet y a la librería de Primefaces. Lo más importante es que os quedéis con como se configura el proyecto, el ejemplo es eso un ejemplo.
Cualquier duda o sugerencia en la zona de comentarios.
Saludos.
muchas gracias por el tutorial, tengo un problema, lo estoy trabajando con Spring Portlet MVC, pero en el archivo portlet.xml me aparece un error en la clase portletfaces.bridge
Puede estar estas dos lineas de codigo juntas? la del spring y la del primefaces?
org.springframework.web.portlet.DispatcherPortlet
org.portletfaces.bridge.GenericFacesPortlet
Tambn tengo problemas en las dependencias. He agregado los repositorios y me dice que me falta esto:
3/05/11 11:29:53 AM COT: Missing artifact com.sun.faces:jsf-impl:jar:2.0.4-b09:compile
3/05/11 11:29:53 AM COT: Missing artifact org.portletfaces:portletfaces-brIdge:jar:2.0.0-BETA3:compile
Hola gabohacker,
Un portlet sólo puede ser implementado por un bridge, por lo tanto debes decidirte entre hacerlo con Primefaces directamente o utilizar Spring MVC integrándolo con Primefaces.
Para el problema de las dependencias prueba a realizar un mvn clean install desde el terminal, a mi también me ha dado problemas esto desde dentro de Eclipse.
Saludos.
Ruben muchas Gracias por tu respuesta, que lineas de codigo tengo que utilizar para utilizar Spring integrandolo con PrimeFaces?
Muchas Gracias por tu respuesta.
Hola gabohacker,
No puedo decir en un comentario como hacer un portlet con Spring MVC y utilizando Primefaces. Pero me has dado una buena idea para un próximo tutorial. Dame un poco de tiempo, lo desarrollo y te lo dedico.
Saludos.
Estupendo Ruben
Muchas Gracias lo estare esperando! 🙂
Excelente, ya lo implemente, super fácil trabajar con jsf 2.0. Pero tengo una pregunta, como puedo trabajar persistencia???, debería crear el proyecto EJB y enlazarlo al proyecto web???, cuando se publique dicho portlet con persitencia como se haría, o como se haría????
Saludos.
Hola amigo, tengo un proble espero me puedas ayudar. Estoy en un proyecto donde uso un pojo en la capa de \\\’Vista\\\’, muestro los datos en un dataTable y dar click en el botón de \\\’Editar\\\’ de cada registro me los debe mostrar en un inputText esto no lo hace me manda un error, de Caused by: javax.el.PropertyNotFoundException: Objetivo inalcanzable, lo raro esque cuando lo muestro dentro de un outputText, funciona sin problema, que estoy haciendo mal?
he probado con primeFaces 2.2 y 3.0.M3 y tengo el mismo problema
ya he declarado mi clase como
@ManagedBean
@RequestScoped
@ViewScoped
Perfecto como funciona, lo hice con icefaces, pero el inconveniente es que necesito que el portlet me aparezca directamente a la hora de hacer un vinculo a la pagina donde lo tengo, porque sino me toca entrar como administrador y selecciona preferencias y es duro con el usuario que elija siempre dicha opción.
Gracias de antemano.
elpeonsolitario, Creo que el problema que se da en el pojo que esta manejando es que no lo tiene serializable en la declaración de la clase ponga implements serializable
Hola como estas, mira me sale el mismo error que al compañero elpeonsolitario me sale este error,
javax.el.PropertyNotFoundException: /views/pacienteCreate.xhtml @54,143 value=»#{pacienteController.paciente.obraSocial.obraSocialId}»: Objetivo inalcanzable, ‘obraSocial’ devolvió nulo
Espero puedas dar una mano, muchas gracias
intente poner serializable y nada, sigue dando el mismo error. que puede ser=???
Que tal
Espero me puedas echar la mano
Estoy desarollando un portlet con Icefaces, pero me manda un error raro cuando le doy click a algún botón o liga, que son componentes de ICE (commandButton o commandLink)
De entrada, el método en el BackingBean nunca es ejecutado, ya probe con action y con actionListener y en ningún caso es ejecutado, revisando la consola de Javascript, lanza muchos errores de que no encuentra funciones de javascript, y creo que por ahi va mi error, pero no logró identificar que es lo que me falta para que ya ejecute las acciones de mis componentes.
Los errores son de este tipo:
Fecha y hora: 01/08/2013 11:25:57 p.m.
Error: ReferenceError: jsf is not defined
Archivo de origen: http://200.77.233.50/wps/myportal/experism/prueba/!ut/p/b1/7ZPbaoNAEIafJU-ws3U9XZqgxrpaxVPcGxFZUouJVo2QPH1NKJQQspQWmpvO3cD3MT8MP2Iox0TSnkAniow2iO3Lqd6WY93uy-a8M6VQVD-heqRgjQYATqrSla8AhjWZgXwG4M4YcO2D5SzBsSTHlz0f2zF8-vcASehrnir2Qf-m_7P8D_dX8r__SP_P___b_t36GWLCip4bKAIuFbsAogzCEzZB_rrd8TlLztQvzE7k5WwTH2JNvRzKej60h77iKKzK6pVTPvEmKLccRWgDpIjetM6l5mEAc6SxSUZcjy6tyEST7gXnuucOnRclRXo89tlJSpPUCI3x-fROwsUC7VhjXY3u1MHkmR_I3mUc/
Línea: 1
Fecha y hora: 01/08/2013 11:25:57 p.m.
Error: TypeError: am.log is undefined
Archivo de origen: http://200.77.233.50/wps/myportal/experism/prueba/!ut/p/b1/7ZPdaoNAEEafJU-ws3XV9dKIGpN1a-Jf9CaILKnFxKBGiE9fI4USQqS00Nx07gbOYT4YPpSiBBOJvoBGFBltUXrMumKftUV1zMrrnio7ReUh03wFU-YBOJHKDK4AhgUZgGQA4MHocOuD5czBsSSHyy7HdgCf_iNAmvSpq077oH3T_1n-p_uG_O8_0__z__-2f_d-jNLJil4bOAWMFRuBqQyTJ2yC-KI6iCFLkqpfmB3K88EmHAKqjofiWjTVuc4FWudZ_iaY6ETpZXuBfLQFsvPf6WnFzHMDZssCk7S4aFcsJx0LT6840dy-oa1v9JvLpY57KQojfa0vN5ax1GczdEhL62Y0p_A61_wAwEm6zw!!/
Línea: 1
Fecha y hora: 01/08/2013 11:26:00 p.m.
Error: TypeError: window.onUnload is not a function
Archivo de origen: http://200.77.233.50/wps/myportal/experism/prueba/!ut/p/b1/7ZPdToNAEEafpQ_Q7Kzd5eeyRaCUBVFAYG8Ikg2iUCqlJPr0UmJiGlNiNLE3zt1uzsl8yeRDHCWYLJQrUIlEUYz4NuvLIuvKZptVxzeXUkl2Q6b6ElaYB2Ddy0xzJcCwJgOQDACcmSWc-mBYK7CMheVSx8VmAB_-OWAx6SuOPO2D-k3_Z_kv7mv037-k_-f3_23_vvoR4pMVPTZwChgrNgJTGSZXmAS566YWQ5aEy5-YGdLVYBMXAkUeF0Wt2DeHNhfoNs_yR8FELyovKwTyUQwk9Z-Unc30wx70jgU66XDZ2SwnPQt3NzhJneHP0ObPNZ3n0Wbz0PC7uKVvzYtdWMvXpG-vi9kM1bwyTka1Sq939HfUN4z9/
Línea: 8
Fecha y hora: 01/08/2013 11:26:00 p.m.
Error: TypeError: ice.captureSubmit is not a function
Archivo de origen: http://200.77.233.50/wps/myportal/experism/prueba/!ut/p/b1/04_SjzQ0MbYwMrA0MTPVj9CPykssy0xPLMnMz0vMAfGjzOLNzP1CfSyDzQwtfAIMDDzDzH2c_cwMDA08TIAKIoEKDHAARwNU_QZunk4Gnm7Gnn6mvn6G7iEGUP24FBjj1W_ha45fv4ElkfrJc_-A63c2HdU_kPrpHv-Y-S9cPwpvFgPlIHwKwFkErACfG_Ba4W6i7-eRn5uqnxuV44YMLD0zA9IdFRUBWh526Q!!/dl4/d5/L2dBISEvZ0FBIS9nQSEh/
Línea: 247
Fecha y hora: 01/08/2013 11:26:00 p.m.
Error: TypeError: ice.captureSubmit is not a function
Archivo de origen: http://200.77.233.50/wps/myportal/experism/prueba/!ut/p/b1/04_SjzQ0MbYwMrA0MTPVj9CPykssy0xPLMnMz0vMAfGjzOLNzP1CfSyDzQwtfAIMDDzDzH2c_cwMDA08TIAKIoEKDHAARwNU_QZunk4Gnm7Gnn6mvn6G7iEGUP24FBjj1W_ha45fv4ElkfrJc_-A63c2HdU_kPrpHv-Y-S9cPwpvFgPlIHwKwFkErACfG_Ba4W6i7-eRn5uqnxuV44YMLD0zA9IdFRUBWh526Q!!/dl4/d5/L2dBISEvZ0FBIS9nQSEh/
Línea: 255
Fecha y hora: 01/08/2013 11:26:00 p.m.
Error: TypeError: ice.captureSubmit is not a function
Archivo de origen: http://200.77.233.50/wps/myportal/experism/prueba/!ut/p/b1/04_SjzQ0MbYwMrA0MTPVj9CPykssy0xPLMnMz0vMAfGjzOLNzP1CfSyDzQwtfAIMDDzDzH2c_cwMDA08TIAKIoEKDHAARwNU_QZunk4Gnm7Gnn6mvn6G7iEGUP24FBjj1W_ha45fv4ElkfrJc_-A63c2HdU_kPrpHv-Y-S9cPwpvFgPlIHwKwFkErACfG_Ba4W6i7-eRn5uqnxuV44YMLD0zA9IdFRUBWh526Q!!/dl4/d5/L2dBISEvZ0FBIS9nQSEh/
Línea: 260
Fecha y hora: 01/08/2013 11:26:00 p.m.
Error: TypeError: ice.setupBridge is not a function
Archivo de origen: http://200.77.233.50/wps/myportal/experism/prueba/!ut/p/b1/04_SjzQ0MbYwMrA0MTPVj9CPykssy0xPLMnMz0vMAfGjzOLNzP1CfSyDzQwtfAIMDDzDzH2c_cwMDA08TIAKIoEKDHAARwNU_QZunk4Gnm7Gnn6mvn6G7iEGUP24FBjj1W_ha45fv4ElkfrJc_-A63c2HdU_kPrpHv-Y-S9cPwpvFgPlIHwKwFkErACfG_Ba4W6i7-eRn5uqnxuV44YMLD0zA9IdFRUBWh526Q!!/dl4/d5/L2dBISEvZ0FBIS9nQSEh/
Línea: 261
Fecha y hora: 01/08/2013 11:26:00 p.m.
Error: TypeError: a5.configuration is undefined
Archivo de origen: http://200.77.233.50/wps/myportal/experism/prueba/!ut/p/b1/7ZPdaoNAEEafJU-ws3XV9dKIGpN1a-Jf9CaILKnFxKBGiE9fI4USQqS00Nx07gbOYT4YPpSiBBOJvoBGFBltUXrMumKftUV1zMrrnio7ReUh03wFU-YBOJHKDK4AhgUZgGQA4MHocOuD5czBsSSHyy7HdgCf_iNAmvSpq077oH3T_1n-p_uG_O8_0__z__-2f_d-jNLJil4bOAWMFRuBqQyTJ2yC-KI6iCFLkqpfmB3K88EmHAKqjofiWjTVuc4FWudZ_iaY6ETpZXuBfLQFsvPf6WnFzHMDZssCk7S4aFcsJx0LT6840dy-oa1v9JvLpY57KQojfa0vN5ax1GczdEhL62Y0p_A61_wAwEm6zw!!/
Línea: 1
Fecha y hora: 01/08/2013 11:26:02 p.m.
Error: TypeError: ice.onBeforeSubmit is not a function
Archivo de origen: http://200.77.233.50/wps/myportal/experism/prueba/!ut/p/b1/7ZPdaoNAEEafJU-ws3XV9dKIGpN1a-Jf9CaILKnFxKBGiE9fI4USQqS00Nx07gbOYT4YPpSiBBOJvoBGFBltUXrMumKftUV1zMrrnio7ReUh03wFU-YBOJHKDK4AhgUZgGQA4MHocOuD5czBsSSHyy7HdgCf_iNAmvSpq077oH3T_1n-p_uG_O8_0__z__-2f_d-jNLJil4bOAWMFRuBqQyTJ2yC-KI6iCFLkqpfmB3K88EmHAKqjofiWjTVuc4FWudZ_iaY6ETpZXuBfLQFsvPf6WnFzHMDZssCk7S4aFcsJx0LT6840dy-oa1v9JvLpY57KQojfa0vN5ax1GczdEhL62Y0p_A61_wAwEm6zw!!/
Línea: 1
El Portal server que estyo utilizando es el de WebSphere, no se si me falte hacer alguna configuración especial para WebSphere…
Ojala me puedas echar la mano
Saludos!!
Hola Ruben
A pesar del tiempo transcurrido consulto, ¿salió a la luz en algun momento el articulo «portlet con Spring MVC y utilizando Primefaces» que mencionaste por ahí?.
Agradecería si lo has hecho.
Saludos desde Chile.