Level Up!

martes, 20 de julio de 2010

Nuestro primer Portlet en Liferay

Hasta el momento hemos visto cómo configurar Liferay sobre un Servidor Glassfish v3 para producción. Esto nos permite tener un Portal en blanco listo para que nosotros le configuremos todo. Es decir, el Liferay que viene preconfigurado con el GF, Tomcat o Jetty que está disponible en la página de descarga de liferay.com, tiene contenido preparado, textos de ejemplo, temas, aplicaciones completas, etc. Además que viene configurado con HSQLDB. Si al preconfigurado le cambiamos el acceso a la base de datos para que utilice el MySQL o cualquiera, en ese momento todo el contenido del Portal estará en blanco.

Recomiendo la versión preconfigurada de liferay para conocer un poco cómo funciona, y además, para usarlo como caja de arena para probar nuestros portlets.

En este post veremos cómo hacer un Portlet para Liferay usando NetBeans 6.x

Quizás te preguntarás por qué quiero usar más GlassFish que Tomcat, así sea para una aplicación web simple. No tengo nada en contra de Tomcat, fue mi primer contenedor Servlet/JSP que utilicé (exactamente la versión 3). Es rápido y simple de usar. Pero para mi me es un problema cuando quiero gestionar con base de datos. Tomcat maneja su Pool de conexiones de manera eficiente, pero configurarlo no es muy agradable que digamos (editar un archivo .xml que es parte del .war no creo que sea muy portable si quiero pasar de desarrollo a producción sin editar nada) Mientras que en GlassFish la configuración del DataSource se hace desde la misma consola del servidor.
Bueno, esto fue un offtopic del post, explicando porqué uso más GlassFish que Tomcat.

Comencemos con la preparación de nuestro NetBeans para desarrollar un portlet:

Configurando NetBeans con un Servidor Liferay+Glassfish v3

Previamente ya debe estar instalado los plugins del PortalPack, que lo vimos en un post anterior.

  1. Abrimos nuestro NetBeans y vayamos al panel de Prestaciones (Services) con Ctrl+5. Abrimos el nodo "Servidores" y hacemos clic derecho sobre ese nodo, seleccionando la opción "Agregar Servidor".





  2. Seleccionamos de la lista "Liferay Portal Server 5.1.x/5.2.x" y hacemos clic en Siguiente.








  3. Seleccionamos el tipo de Servidor a GlassFish, y el GlassFish Home a "C:\glassfishv3\glassfish".







  4. Clic en "Siguiente". Dejamos los valores por omisión, y clic en "Terminar"

Ejecutando Liferay desde NetBeans

Bien, ahora que ya tenemos nuestro NetBeans configurado con Liferay, será bueno primero iniciar el Liferay para ver sobre donde vamos a trabajar. Para ello, hacemos clic derecho sobre el ícono del Liferay que hemos acabado de agregar al NetBeans, y seleccionamos "Start".


... y si tienes un computador tan lento como el que tengo en la oficina, en unas horas en unos momentos, se mostrará el Liferay en el navegador.



Nuestro primer portlet básico

Un portlet es en realidad una aplicación web que se distribuye en .war y que tiene archivos .xml de despliegue adicionales. Como aplicación web, también cuenta con su ruta de contexto (context-path), sus configuraciones del web.xml y demás. Ahora con la versión JavaEE6, también puede contener EJB 3.1, ya que - como acabo de decir - es una aplicación web. Solo que esta aplicación web no se desplegará desde la consola del contenedor web, sino desde el mismo contenedor de portlets, en este caso, desde liferay.

Creando un proyecto web

  1. Así que comencemos creando una aplicación web desde Archivo > Nuevo proyecto > Java Web > Web Application.






  2. Clic en Siguiente. Luego indicamos el nombre del proyecto y su ubicación. Le ponemos que se llamará SimplePortlet, y tomar la ubicación predeterminada.






  3. Clic en Siguiente. Seleccionamos el servidor donde se desplegará. En este caso seleccionamos el que acabamos de agregar al IDE hace un momento. Notar que cuenta la versión del Java EE y la ruta de contexto.







  4. Clic en Siguiente. Cuando nos pida los "Frameworks" a utilizar, activamos el que dice "Portlet Support". Y más abajo dice "Create Portlet". Lo dejamos desactivado para crearlo posteriormente.








  5. Clic en Terminar.
Vemos que es un proyecto web mas archivos .xml adicionales....
Insisto diciendo que es un proyecto web, para que no sea chocante tratar de pensar que es otro tipo de proyecto y no se hagan preguntas como:
  • ¿Puedo ponerle mis imágenes? ¿Dónde?
  • ¿Puedo usar .css?
  • ¿Puedo poner .js?
  • ¿Dónde pongo las clases?
  • etc... etc.. etc
Este proyecto podrá tener más de un portlet. Así que comenzaremos a crear el primero.

Creado un portlet


Advertencia: Al momento de hacer este post, encontré problemas para desplegar un portlet desde NetBeans + PortalPack al Liferay/GFv3. Esto es porque el PortalPack considera que el Servidor a utilizar es Liferay/GFv2 o Tomcat. Utiliza el JSR88 para desplegarlo sobre GFv2, y este JSR88 ya no está disponible para GFv3. En resumen. Si utilizas el Liferay+GFv2, el despliegue será inmediato. Pero para este post haremos la manera no cómoda pero que funciona: desplegar el Portlet desde la Consola de Liferay.
  1. Hagamos clic en Nuevo > Archivo nuevo (Ctrl+N) y seleccionamos Portlets > Portlet







  2. Clic en Siguiente. Luego escogemos como nombre de la clase Portlet FactorialPorlet del paquete portlets. Eso es solo la característica de la clase. Pero esta clase debe tener características como Porlet, por ejemplo el nombre, descripción, etc. Así que pongamos los siguientes valores:






    • PortletName: FactorialPortlet
    • Portlet Display Name: Factorial Portlet
    • Porlet Description: Portlet que calcula el factorial
    • Portlet title: Factorial en Portlet
    • Portlet Short Title: Factorial
    • Activar los checks  "Edit" y "Help". Estas serán páginas adicionales que interactuará con el usuario.

  3. Clic en Siguiente. Activamos el check para que nos cree los .jsp correspondientes.







  4. Clic en Terminar.

Con esto nos habrá creado una clase FactorialPortlet, y dentro de WEB-INF/jsp estarán los archivos .jsp que serán utilizados para el interfaz de usuario.

Vemos que hay dos métodos que nos llaman la atención (que nos recuerdan al doGet y doPost de los Servlets) processAction(), doView, doEdit y doHelp. Estos métodos son invocados por el Portal para mostrar una página dependiendo de la petición que haya hecho el usuario. Si solo quiere ver, se ejecutará el doView, si va a editar las preferencias del portlet, ejecutará doEdit, y si quiere ver la ayuda del portlet, se ejecutará doHelp. Pero cuando se quiere atender una petición, se ejecutará el método processAction(). Notemos que dentro está la clase PortletRequestDispatcher que no es más que una especialización de la clase RequestDispatcher utilizada en los servlet bajo el modelo MVC. Así que, aquí no hay modo de fallar :).

Ahora, editemos el archivo FactorialPortlet.java para que calcule el Factorial. Primero, el método que hace el cálculo.

    static long factorial(long base) {        if (base < 2) {            return 1;        }        return base + factorial(base - 1);    }

Y, editemos el método processAction() para leer un parámetro de la web, lo calculamos, y lo mostramos al usuario.

    public void processAction(ActionRequest request, ActionResponse response) throws PortletException, IOException {        String numero = request.getParameter("numero");        System.out.println("Parametro leido:" + numero);        if (numero != null && !numero.isEmpty()) {            try {                long $numero = Long.parseLong(numero);                long factorial = factorial($numero);                System.out.println("resultado:" + factorial);                request.setAttribute("factorial", factorial);            } catch (NumberFormatException ex) {                ex.printStackTrace();            }        }    }

Ahora, nos falta el formulario. Abramos el archivo FactorialPortlet_view.jsp, y escribamos el siguiente código:
<%@page contentType="text/html"%><%@page pageEncoding="UTF-8"%><%@ page import="javax.portlet.*"%><%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%><h3>Cálculo de factorial</h3><form action="<portlet:actionURL/>" method="post">    Ingrese un número:    <input type="text" name="numero" /><br/>    <button type="submit">Calcular</button>    <div>        Resultado: ${factorial}    </div></form>

La mayor parte del formulario nos es conocido: tiene input, botones, imprime resultado, etc. Pero el tag <portlet:actionURL/> quizás no sea claro, pero puede darnos la idea de qué es. Este tag devuelve la ubicación del mismo portlet dentro de toda la página de portlets. Me explico mejor:

Recordemos que cuando hacemos un formulario en JSP, siempre el action debe apuntar a una dirección web que recibirá los parámetros del formulario: puede ser un Servlet u otro JSP. Ahora, ¿qué pasaría si tuvieramos varios forms en una misma página que apuntan a diferentes direcciones? ¿Cómo hacemos para que diferencie que un formulario es diferente a otro y diferenciar las peticiones? Pues, hacer que el url del action sea totalmente diferente. Pues bien, bajo la misma lógica, el tag <portlet:actionURL/> nos ahorra saber cuál es el URL del Portlet que debemos ejecutar, además que le pone una identificación única para diferenciarlos de los demás Portlets.

Creando el archivo de despliegue

Para crear un archivo .war que contiene el Portlet, es bastante simple. Es tan igual como cuando se crea un archivo. Clic derecho el ícono de proyecto, y seleccionar Limpiar y Construir (Clean and Build).

Con esto, nos creará un archivo .war. Veamos donde lo creado en el panel de Salida (Ctrl+4) del NetBeans.

Desplegando el .war

Para desplegar un .war tenemos dos maneras: la larga, y la corta. Solo mencionaré la forma corta. Es simple: basta con copiar el .war en la carpeta "deploy" del GlassFish...


...esperamos unos segundos y el archivo desparecerá. Esperamos unos segundos más y estará desplegado en el Servidor.

Colocando el Portlet en el Portal

Primero debemos iniciar la sesión (por omisión es test@liferay.com con contraseña test). Luego, en el parte superior derecha está menú "dock", al que le damos clic y seleccionamos "Add application"
Esto hará que se muestre un panel en la margen izquierda y veamos una ventana con todas los portlets disponibles, agrupados por categorías. Nuestro portlet está en la categoría "User_Portlets".



Le damos clic en "Add" para agregar el Portlet, o si gustamos, lo arrastramos y lo soltamos en cualquier parte de la página.

Y lo hacemos funcionar...


Nota: Para cambiar la categoría del Portlet, debemos editar el archivo liferay-display.xml desde NetBeans.

Conclusión

Este post me fue lo más accidentando que me he atrevido a hacer. Pudo haber sido más simple o más completo, pero a medida que hago el tutorial, también construyo el proyecto para asegurarme que todo lo que digo sea correcto. Pero me encontré con problemas de versiones, componentes faltantes, y más cosas no esperadas. Quería terminar con el .JSF, pero ya no me dio el  tiempo. Será para otro post. (También tengo que hacer cosas en donde trabajo.) En fin. Este post me motivó hacerlo ya que implementé el Liferay para el Site de la oficina donde trabajo. Aún no está del todo terminado, hicimos un par de portlets que funcionan bien, solo nos falta hacer un par más, implementar un nuevo Theme con los colores de la oficina y listo. Así que cada cosa que encuentro, lo voy colocando en mi blog.

Un tip importante que aprendí cuando hemos desarrollado los portlets de manera rápida (ya que mi computador es bastante lento para desplegar un .war en liferay), es:
  1. Cambiar en las propiedades del proyecto a para que utilice el GlassFish v3 en lugar del Liferay
  2. Desarrollar, probar, ejecutar, depurar como si se tratase de una aplicación web. Considerando los elementos de portlets, adaptar la aplicación para que funcione sin él. (Recordar que el método processAction() es similar a un Servlet, así que convendría utilizar un servlet por mientras.
  3. Luego, cuando esté listo, acomodar los tags de la aplicación para pasar a liferay.
  4. Cambiar en las propiedades del proyecto para que utilice Liferay en lugar de GlassFish v3.
  5. Construir el .war
  6. Desplegar el .war al Liferay.
 Se pueden agregar más servlets, componentes JQuery, Ajax, Dojo, etc.

Espero que te haya hecho de utilidad.

El proyecto que utilicé en este post está aquí: http://java.net/downloads/apuntes/samples/web/SimplePortlet.tar.gz