icono_twiter icono LinkedIn
Rubén Aguilera Díaz-Heredero

Consultor tecnológico de desarrollo de proyectos informáticos.

Ingeniero en Informática, especialidad en Ingeniería del Software

Puedes encontrarme en Autentia: Ofrecemos servicios de soporte a desarrollo, factoría y formación

Somos expertos en Java/J2EE

Ver todos los tutoriales del autor

Fecha de publicación del tutorial: 2011-05-02

Tutorial visitado 13.962 veces Descargar en PDF
CRUD con Spring MVC Portlet

Creación de un portlet con Primefaces

0. Índice de contenidos.

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:


	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:


	
		maven2-repository.dev.java.net
		http://download.java.net/maven/2
	
	
		maven2-repository.jboss.org
		http://repository.jboss.org/maven2
	
	
		maven2-repository-portletfaces.org
		http://repo.portletfaces.org/mvn/maven2
	
	
		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
		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:


	
		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:



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
		true
		false
	

liferay-display.xml


	
		<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:



	
Welcome to Gambit Portlet Powered by PrimeFaces

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:


	
	
		
			
				<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:

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.

A continuación puedes evaluarlo:

Regístrate para evaluarlo

Por favor, vota +1 o compártelo si te pareció interesante

Share |
Anímate y coméntanos lo que pienses sobre este TUTORIAL:

Fecha publicación: 2013-08-12-23:46:15

Autor: ibanhoe

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!!

Fecha publicación: 2012-02-15-16:17:52

Autor: jlopez

intente poner serializable y nada, sigue dando el mismo error. que puede ser=???

Fecha publicación: 2012-02-15-15:57:02

Autor: jlopez

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

Fecha publicación: 2011-11-08-21:35:49

Autor: fmarin

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

Fecha publicación: 2011-11-08-21:32:50

Autor: fmarin

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.

Fecha publicación: 2011-10-26-18:12:51

Autor: elpeonsolitario

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?

<h:inputText value="#{catalogoChequesVista.seleccionado.nombre}" />

he probado con primeFaces 2.2 y 3.0.M3 y tengo el mismo problema
ya he declarado mi clase como
@ManagedBean
@RequestScoped
@ViewScoped

Fecha publicación: 2011-10-26-18:04:16

Autor: elpeonsolitario

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?

<h:inputText value="#{catalogoChequesVista.seleccionado.nombre}" />

he probado con primeFaces 2.2 y 3.0.M3 y tengo el mismo problema
ya he declarado mi clase como
@ManagedBean
@RequestScoped
@ViewScoped

Fecha publicación: 2011-09-30-17:02:25

Autor: fmarin

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.

Fecha publicación: 2011-05-11-01:52:58

Autor: gabohacker

Estupendo Ruben
Muchas Gracias lo estare esperando! :)

Fecha publicación: 2011-05-04-16:05:20

Autor: rubenagui

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.

Fecha publicación: 2011-05-04-16:01:33

Autor: gabohacker

Ruben muchas Gracias por tu respuesta, que lineas de codigo tengo que utilizar para utilizar Spring integrandolo con PrimeFaces?

Muchas Gracias por tu respuesta.

Fecha publicación: 2011-05-04-12:30:29

Autor: rubenagui

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.

Fecha publicación: 2011-05-03-18:31:00

Autor: gabohacker

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

Fecha publicación: 2011-05-03-16:52:14

Autor: gabohacker

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?

<portlet-class>org.springframework.web.portlet.DispatcherPortlet</portlet-class>
<portlet-class>org.portletfaces.bridge.GenericFacesPortlet</portlet-class>