1 Desarrollo de Plugins (Parte 2)Liferay 6.2 Desarrollo de Plugins (Parte 2)
2 Portlets Ejemplo de Aplicación FuncionalController En primer lugar se deben agregar las dependencias de los taglibs que se utilizarán en la aplicación: En el archivo web.xml agregamos el contenido del snippet 01-web.xml de la sección PortalDev-04-MVC: También pueden ser agregadas al archivo liferay-plugin-package.properties como dependencias mediante el IDE.
3 Portlets Ejemplo de Aplicación FuncionalPortlet Controller Debido a que extendimos de MVCPortlet, los métodos que corresponden a los diferentes portlets modes están ocultos: doView() doEdit() doHelp() Es posible editarlos, pero para el ejemplo no es necesario y dejamos la implementación por defecto. Siguiendo el patrón establecido en el Liferay MVCPortlet framework se utilizará un render parameter para decidir que vista se le desplegará al usuario: «mvcPath».
4 Portlets Ejemplo de Aplicación FuncionalImplementación de la Vista Creamos un archivo llamado /html/init.jsp, y le agregamos las siguientes directivas (básicas para todo proyecto Liferay), utilizando el snippet 02-init.jsp:
5 Portlets Ejemplo de Aplicación FuncionalImplementación de la Vista El archivo init.jsp será incluido en todos los demás JSP para que incorpore las dependencias descritas El tag
6 Portlets Ejemplo de Aplicación FuncionalImplementación de la Vista Local Variable Class Comentario renderRequest javax.portlet.RenderRequest Disponible si el JSP es incluido desde el método render renderResponse javax.portlet.RenderResponse actionRequest javax.portlet.ActionRequest Disponible si el JSP es incluido desde el método processAction actionResponse javax.portlet.ActionResponse eventRequest javax.portlet.EventRequest Disponible si el JSP es incluido desde el método processEvent eventResponse javax.portlet.EventResponse resourceRequest javax.portlet.ResourceRequest Disponible si el JSP es incluido desde el método serveResource resourceResponse javax.portlet.ResourceResponse Local Variable Class Comentario portletConfig javax.portlet.PortletConfig portletSession javax.portlet.PortletSession portletSessionScope javax.util.Map
7 Portlets Ejemplo de Aplicación FuncionalImplementación de la Vista El tag
8 Portlets Ejemplo de Aplicación FuncionalImplementación de la Vista (Manufacturer) Continuando con la implementación de las vistas, crearemos los siguientes jsp para manufacturer: /html/manufacturer/view.jsp -> Reemplazar el contenido por el snippet 03-Manufacturer view.jsp
9 Portlets Ejemplo de Aplicación FuncionalImplementación de la Vista (Manufacturer) /html/manufacturer/edit_manufacturer.jsp -> Reemplazar el contenido por el snippet 04-Manufacturer edit_manufacturer.jsp:
10 Portlets Ejemplo de Aplicación FuncionalImplementación de la Vista (Manufacturer)
11 Portlets Ejemplo de Aplicación FuncionalImplementación de la Vista (Part) Ahora crearemos los siguientes jsp para parts: /html/parts/view.jsp -> Reemplazar el contenido por el snippet 05-Part view.jsp
12 Portlets Ejemplo de Aplicación FuncionalImplementación de la Vista (Part) /html/parts/edit_part.jsp -> Reemplazar el contenido por el snippet 06-Part edit_part.jsp:
13 Portlets Ejemplo de Aplicación FuncionalImplementación de la Vista (Part)
14 Portlets Ejemplo de Aplicación FuncionalImplementación de la Vista (Part) En este punto podemos deployar el proyecto, y agregar el portlet Parts, para ver como va quedando:
15 Portlets Ejemplo de Aplicación FuncionalImplementación de la Vista (Part) Si da problemas al deployar, incluir las dependencias de la siguiente forma:
16 Portlets Ejemplo de Aplicación FuncionalPortlet Actions En esta parte veremos como las Action URLs son utilizadas para enlazar las acciones de la vista con los métodos del controlador Existen tres diferentes acciones que pueden ser realizadas desde el portlet Manufacturer: Add manufacturer Update Manufacturer Delete Manufacturer
17 Portlets Ejemplo de Aplicación FuncionalPortlet Actions Agregamos el snippet 01-Manufacturer Actions de la sección PortalDev-05-MVC Actions, a la clase ManufacturerPortlet.java, y organizamos los imports. Agregamos el snippet 02-Part Actions de la sección PortalDev-05-MVC Actions, a la clase PartsPortlet.java, y organizamos los imports. Importaciones Manufacturer: import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.util.ParamUtil; import com.liferay.portal.kernel.util.WebKeys; import com.liferay.portal.theme.ThemeDisplay; import com.liferay.training.parts.model.Manufacturer; import com.liferay.training.parts.service.ManufacturerLocalServiceUtil; import com.liferay.util.bridges.mvc.MVCPortlet; Importaciones Parts: import java.util.Date; import java.util.Locale; import java.util.Map; import com.liferay.portal.kernel.util.LocalizationUtil; import com.liferay.portal.util.PortalUtil; import com.liferay.training.parts.model.Part; import com.liferay.training.parts.service.PartLocalServiceUtil;
18 Portlets Ejemplo de Aplicación FuncionalPortlet Actions (Manufacturer) Método AddManufacturer:
19 Portlets Ejemplo de Aplicación FuncionalPortlet Actions (Parts) Método addPart:
20 Portlets Ejemplo de Aplicación FuncionalPortlet Actions A esta altura deberíamos poder probar y agregar Parts y Manufacturers sin problemas.
21 Portlets Ejemplo de Aplicación FuncionalLiferay Search Container Para trabajar con listas de objetos en la vista, podríamos crear nuestro propio mecanismo, pero Liferay ya ha solucionado esto, mediante el componente Liferay SearchContainer Este componente trabaja en conjunción con las librerías de tags de Liferay UI, para proveer una interfaz wrapper alrededor de listas de objetos. Debido a que SearchContainer es un componente estándar de las librerías de Liferay UI, la aplicación se parece a una de las aplicaciones core del portal.
22 Portlets Ejemplo de Aplicación FuncionalLiferay Search Container El tag
23 Portlets Ejemplo de Aplicación FuncionalLiferay Search Container (Manufacturer) Continuando con el ejercicio, debemos agregar al final del archivo /html/manufacturer/view.jsp, el contenido del snippet 03-Manufacturer Search Container También se debe crear un nuevo archivo llamado /html/manufacturer/manufacturer_actions.jsp, y agregar el contenido del snippet 04-Manufacturer actions
24 Portlets Ejemplo de Aplicación FuncionalLiferay Search Container (Manufacturer)
25 Portlets Ejemplo de Aplicación FuncionalLiferay Search Container (Manufacturer) JSP de acciones:
26 Portlets Ejemplo de Aplicación FuncionalLiferay Search Container (Parts) En el caso de Parts Portlet, debemos agregar al final del archivo /html/parts/view.jsp, el contenido del snippet 05-Part Search Container También se debe crear un nuevo archivo llamado /html/parts/parts_actions.jsp, y agregar el contenido del snippet 06-Part actions
27 Portlets Ejemplo de Aplicación FuncionalLiferay Search Container (Parts)
28 Portlets Ejemplo de Aplicación FuncionalLiferay Search Container Importante: Es una buena práctica escapar los valores siempre cuando sea posible! Alloy UI, por defecto escapa los inputs de sus formularios. Si no se quiere que se escapen por defecto, se puede deshabilitar esta opción.
29 Portlets Ejemplo de Aplicación FuncionalLiferay Search Container Vista del componente Search Container:
30 Portlets Ejemplo de Aplicación FuncionalPortlet Actions Finalmente agregamos el contenido de los snippets 07-Manufacturer Actions y 08-Part Actions, a las clases ManufacturerPortlet.java y PartsPortlet.java respectivamente, y organizar los imports Los snippets contienen el código para las acciones de update y delete para ambas entidades Imports Parts: import java.util.Date; import java.util.Locale; import java.util.Map; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import com.liferay.portal.kernel.exception.SystemException; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.util.LocalizationUtil; import com.liferay.portal.kernel.util.ParamUtil; import com.liferay.portal.kernel.util.WebKeys; import com.liferay.portal.theme.ThemeDisplay; import com.liferay.portal.util.PortalUtil; import com.liferay.training.parts.model.Part; import com.liferay.training.parts.service.PartLocalServiceUtil; import com.liferay.util.bridges.mvc.MVCPortlet; Imports Manufacturer: import com.liferay.training.parts.model.Manufacturer; import com.liferay.training.parts.service.ManufacturerLocalServiceUtil;
31 Portlets Ejemplo de Aplicación FuncionalUser Feedback, Validación y Localización Es posible utilizar los mecanismos de los demás frameworks, pero Liferay también provee estas características para que las utilicen los usuarios. Los portlets que las utilicen actuarán más como aplicaciones nativas de Liferay. Para utilizar las propiedades de la localización en Liferay, se debe configurar un archivo llamado Language.properties (resource bundle). El nombre del archivo de lenguajes (fully qualified) debe ser configurado en el archivo portlet.xml mediante el tag
32 Portlets Ejemplo de Aplicación FuncionalUser Feedback, Validación y Localización
33 Portlets Ejemplo de Aplicación FuncionalUser Feedback, Validación y Localización Archivo de mensajes:
34 Portlets Ejemplo de Aplicación FuncionalUser Feedback, Validación y Localización Continuando con el ejercicio, agregamos el contenido del snippet 01-Language Properties, de la sección PortalDev-06-Feedback, Validation, Language, al archivo /content/Language.properties También agregamos el contenido del snippet 02-Success Messages, justo después del tag
35 Portlets Ejemplo de Aplicación FuncionalUser Feedback, Validación y Localización En el archivo ManufacturerPortlet.java agregar los snippets: 03-Manufacturer-SessionMessages-added 04-Manufacturer-SessionMessages-updated 05-Manufacturer-SessionMessages-deleted Se deben agregar donde estén los comentarios en cada método respectivo, y organizar los imports: En este punto podemos probar los mensajes configurados.
36 Portlets Ejemplo de Aplicación FuncionalValidaciones Liferay ofrece validaciones del lado del servidor y del lado del cliente. Alloy UI provee validación de formularios del lado del cliente. Validaciones en el Cliente Para usar el validador de formularios de Alloy, se debe modificar el siguiente archivo generado al crear el servicio: /docroot/WEB-INF/src/META-INF/portlet-model-hints.xml Aquí se configura el despliegue y validación de los campos del formulario: reemplazamos el contenido de este archivo por el snippet 06-AUI Form Validator
37 Portlets Ejemplo de Aplicación FuncionalValidaciones
38 Portlets Ejemplo de Aplicación FuncionalValidaciones Este tipo de validación tiene un bug en Liferay 6.2, y es probable que las validaciones solo funcionen en el formulario de edición Custom Validations: Para especificar validaciones personalizadas, se puede usar el tag
39 Portlets Ejemplo de Aplicación FuncionalValidaciones en el Servidor Las utilidades de validaciones del lado del servidor son implementadas en la clase: com.liferay.kernel.util.Validator Esta clase provee métodos utilitarios para validaciones de datos y chequeo de formatos
40 Portlets Ejemplo de Aplicación FuncionalValidaciones en el Servidor Continuando con el ejemplo, creamos la clase ManufacturerValidator.java en el package com.liferay.training.parts.portlet, y reemplazar el contenido por el snippet 07-Manufacturer Validator Reemplazar el método addManufacturer() en ManufacturerPortlet.java, con el contenido del snippet 08-addManufacturer(), y organizar los imports
41 Portlets Ejemplo de Aplicación FuncionalValidaciones en el Servidor
42 Portlets Ejemplo de Aplicación FuncionalValidaciones en el Servidor
43 Portlets Ejemplo de Aplicación FuncionalValidaciones en el Servidor Se debe realizar el mismo procedimiento con los snippets 09-updateManufacturer() y 10-deleteManufacturer() , y organizar los imports Agregar el contenido del snippet 11-More Properties al final del archivo content/Language.properties Editar el archivo /html/manufacturer/edit_manufacturer.jsp, reemplazando el contenido de
44 Portlets Ejemplo de Aplicación FuncionalValidaciones en el Servidor Para finalizar, se debe realizar el mismo procedimiento para Parts Portlet, utilizando los snippets 13-Event More Properties, 14-edit-part.jsp Crear la clase PartValidator.java en el package com.liferay.training.parts.portlet, y reemplazar el contenido por el snippet 15-Part Validator Reemplazar los métodos de PartsPortlet.java por el contenido del snippet 16-Part Methods Probar los cambios realizados
45 Portlets Ejemplo de Aplicación FuncionalValidaciones en el Servidor
46 Portlets Ejemplo de Aplicación FuncionalPermisos Los permisos son otorgados o quitados en Liferay Portal basados en un par resource-action. Los recursos pueden ser:
47 Portlets Ejemplo de Aplicación FuncionalPermisos Los permisos son otorgados a los roles, y los roles se le asignan a los usuarios. Para habilitar los permisos en model resource, es necesario agregar un registro de resource a la base de datos, al mismo tiempo que se agrega un registro de la entidad. Liferay usa los resources para los chequeos de permisos Los recursos quedan linkeados por base de datos a las entidades a los que pertenecen. Los portlets necesitan agregar o eliminar recursos cada vez que se agregan o eliminan entidades.
48 Portlets Ejemplo de Aplicación FuncionalPermisos Reemplazar el método addManufacturer() de la clase ManufacturerLocalServiceImpl.java, por el contenido del snippet 01-Manufacturer Service, y organizar los imports Reemplazar el método addPart() de la clase PartLocalServiceImpl.java, por el contenido del snippet 02-Part Service, y organizar los imports Ejecutar el Service Builder para regenerar las interfaces Imports Manufacturer: import java.util.Date; import java.util.List; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.exception.SystemException; import com.liferay.portal.model.ResourceConstants; import com.liferay.training.parts.model.Manufacturer; import com.liferay.training.parts.service.base.ManufacturerLocalServiceBaseImpl; Imports Parts: import com.liferay.training.parts.model.Part; import com.liferay.training.parts.service.base.PartLocalServiceBaseImpl;
49 Portlets Ejemplo de Aplicación FuncionalPermisos Imports Manufacturer: import java.util.Date; import java.util.List; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.exception.SystemException; import com.liferay.portal.model.ResourceConstants; import com.liferay.training.parts.model.Manufacturer; import com.liferay.training.parts.service.base.ManufacturerLocalServiceBaseImpl; Imports Parts: import com.liferay.training.parts.model.Part; import com.liferay.training.parts.service.base.PartLocalServiceBaseImpl;
50 Portlets Ejemplo de Aplicación FuncionalPermisos Se deben modificar las clases de los portlets para agregar el user ID que ahora es necesario en las llamadas de los servicios Agregar el código del snippet 03-Define userId en los métodos addManufacturer() y addPart() de las clases ManufacturerPortlet.java y PartsPortlet.java El código debe agregarse antes de las líneas ManufacturerLocalServiceUtil.addManufacturer(manufacturer) y PartLocalServiceUtil.addPart(part), y se deben modificar los métodos para agregar el parámetro userId
51 Portlets Ejemplo de Aplicación FuncionalPermisos Configurando Permisos Se definen declarativamente en un archivo XML Una vez definidos, no son necesarias configuraciones adicionales Todo lo que el desarrollador necesita hacer es “envolver“ los elementos con el chequeo de permisos Primero se definirán los permisos, y luego se chequearán en el código
52 Portlets Ejemplo de Aplicación FuncionalPermisos Crear el directorio resource-actions en la raiz: docroot/WEB-INF/src Crear un archivo llamado default.xml dentro del directorio resource-actions Insertar el código del snippet 04-Manufacturer Template en el archivo creado Agregar el contenido del snippet 05-Manufacturer Portlet Permissions entre los tags
53 Portlets Ejemplo de Aplicación FuncionalPermisos Agregar el contenido del snippet 07-Model Permissions después del snippet anterior (permisos asociados al modelo, específicamente acciones de tipo top level) Agregar el contenido del snippet 08-Manufacturer Permissions después del snippet anterior (permisos asociados a manufacturers) Agregar el contenido del snippet 09-Part Permissions después del snippet anterior (permisos asociados a parts)
54 Portlets Ejemplo de Aplicación FuncionalPermisos El proceso de hot-deploy mira en el archivo portlet.preferences para identificar donde se encuentran configurados los permisos, éste archivo debe ir en la raíz del classpath. Creamos el archivo portlet.properties en el directorio WEB-INF/src, y le agregamos el contenido del snippet 10-portlet-properties
55 Portlets Ejemplo de Aplicación FuncionalPermisos
56 Portlets Ejemplo de Aplicación FuncionalChequeo de Permisos Insertar el contenido del snippet 11-Manufaturer Permission Check después del tag
57 Portlets Ejemplo de Aplicación FuncionalChequeo de Permisos
58 Portlets Ejemplo de Aplicación FuncionalChequeo de Permisos Agregaremos chequeo de permisos en el botón Add Manufacturer En el archivo view.jsp del portlet Manufacturer, reemplazamos el código que está dentro del tag
59 Portlets Ejemplo de Aplicación FuncionalChequeo de Permisos Agregamos los permisos respectivos para las acciones de cada registro En el archivo manufacturer/manufacturer_actions.jsp, reemplazamos el contenido del tag
60 Portlets Ejemplo de Aplicación FuncionalChequeo de Permisos En el mismo archivo agregar el contenido del snippet 14-Permissions Action Button, justo antes del tag . Con esto agregamos un link al menú para acceder a la vista de los permisos del recurso
61 Portlets Ejemplo de Aplicación FuncionalChequeo de Permisos Para agregar un link a los permisos de Top Level, en el archivo view.jsp de Manufacturer, agregamos el contenido del snippet 15-Portlet Permissions Button justo antes del tag
62 Portlets Ejemplo de Aplicación FuncionalChequeo de Permisos Vista de permisos Top Level
63 Portlets Ejemplo de Aplicación FuncionalChequeo de Permisos Buena práctica: Es buena idea crear una clase helper para el manejo de los permisos para modelos y entidades particulares, Liferay utiliza esta práctica en su código fuente. Ej: Luego importamos el helper a la página como dependencia:
64 Portlets Ejemplo de Aplicación FuncionalChequeo de Permisos Ejemplo utilización del helper:
65 Portlets Ejemplo de Aplicación FuncionalChequeo de Permisos También podemos hacer los chequeos en forma interna en el portlet para mayor seguridad:
66 Portlets Ejemplo de Aplicación FuncionalChequeo de Permisos En Parts, los permisos son similares, salvo en parts_action.jsp:
67 Portlets Ejemplo de Aplicación FuncionalChequeo de Permisos Permisos Inline Ej: Cuando un usuario intenta ver una entidad específica los permisos son chequeados y aplicados Esto no entrega una buena experiencia de usuario En muchos casos, el Service Builder también genera métodos filterFindBy() y filterCountBy() los cuales toman en cuenta los permisos de View en sus consultas. Para que se generen estos métodos, se deben cumplir las siguientes condiciones: La entidad debe tener una clave primaria primitiva simple La entidad tiene permisos registrados en resource-actions/….xml La entidad tiene campos userId y groupId El método finder tiene un groupId pasado como parámetro
68 Portlets Ejemplo de Aplicación FuncionalChequeo de Permisos Permisos Inline Ej:
69 AplicationDisplay Templates ADTLiferay introduce el contepto de ADT en la versión 6.2 como un nuevo framework para agregar opciones de despliegue personalizado de portlets Cuando un administrador selecciona un ADT para un portlet, se seleccionan en el backend, display settings personalizadas para ese portlet Debido a que los ADTs usan portlet display settings, no requieren ser deployados, y solamente afectan a instancias específicas de portlets El framework ADT utiliza el portlet Dynamic Data Mapping (DDM) para su capa de servicio El portlet DDM también administra todas las operaciones para estructuras y templates para aplicaciones Liferay como web content, documents and media, dynamic datalist, etc. Algunos portlets out-of-the-box utilizan ADT: Asset Publisher, Wiki, Blogs, Document and Media, etc.
70 AplicationDisplay Templates ADT
71 Themes Todos los temas están sobre la base de un tema principal (master theme) que provee un diseño simple. Los plugins flexibles de temas de Liferay proveen control sobre: Todas las imágenes usadas fuera de los portlets Imágenes usadas dentro de los portlets de Lifray (incluyendo íconos) Código HTML de la página (fuera de los portlets) Código HTML de la caja del portlet La posición y comportamiento de los elementos de navegación de la parte superior Con todas esas opciones es posible adaptar Liferay a cualquier diseño creativo.
72 Themes Temas Todos los temas se basan en diferencias del tema defaultEsto reduce el número de archivos y la complejidad en temas custom Los proyectos de temas contienen solamente los CSS, imágenes, JS o templates que son diferentes a los del tema por defecto Tema = Custom Files (css, js, vm, etc.) + Deafult Theme Para el desarrollo de temas se recomienda utilizar el Plugins SDK y el Liferay Developer Studio
73 Themes Temas Cuando se crea un plugin de tema, es posible seleccionar entre tres tecnologías: Freemarker, Velocity o JSP, dependiendo de la selección, será el tipo de plantillas que se crearán para el nuevo tema Base Themes Liferay incluye dos plantillas de temas que son las bases para cualquier tema: _unstyled: Contiene las plantillas e imágenes por defecto. Sus archivos CSS solamente contienen marcadores para agregar reglas de formateo. _styled: Agrega archivos CSS con reglas de formateo El tema clásico está basado en _unstyled y _styled, y agrega los diferentes esquemas de colores Los temas bases pueden ser encontrados en el código fuente de Liferay en: [liferay-source]/portal-web/docroot/html/themes
74 Themes Color Schemes Color Scheme son variciones del mismo temaEl propósito es que el usuario final pueda seleccionar su variante preferida del tema Los esquemas de colores son implementados proveyendo variaciones en los archivos CSS e imágenes del tema base
75 Themes Estructura de un Tema en Plugins SDKTodo el código customizado va en el directorio /docroot/_diff (css, images, templates) Tres cosas pasan cuando un tema es deployado: El tema base _unstyled es copiado primero Despues se copia el tema base _styled Cualquier archivo en _diff desde el tema, es copiado sobre los archivos anteriores
76 Themes Archivos CSS application.css: estilos relacionados a elementos de la aplicación (tabs, datepicker,etc) base.css: Tiene el estilo básico que aplica al portal entero custom.css: Aquí es donde se sobrescribirán los estilos propios dockbar.css: Tiene estilos relacionados al dockbar forms.css: Tiene estilos relacionados a los formularios layout.css: Tiene estilos relacionados a los layouts main.css: Incluye todos los otros CSSs navigation.css: Estilos de la navegación portlet.css: Estilos de los portlets
77 Themes Imágenes common/: Contiene todas las imágenes generalesdockbar/Contiene imágenes para los estilos del dockbar messages/: Contiene imágenes para los diferentes mensajes del portal navigation/: Contiene imágenes apra los estilos de la navegación portlet/: Contiene imágenes relacionadas a la decoración del portlet
78 Themes Templates init.vm: Lee las variables usadas por las otras plantillas init_custom.vm: Usado para sobrescribir o almacenar nuevas variables navigation.vm: Contiene el HTML de la navegación portal_normal.vm: El “index” principal que contiene el HTML base portal_popup.vm: Similar a portal_normal.vm, excepto que este se muestra en popups portlet.vm: Contiene la caja alrededor de todos los portlets Las plantillas descritas son de Velocity, pero también podrían ser de Freemarker (ftl) o JSP (jsp)
79 Themes Otras javascript/: WEB-INF/:javascript.js: Este archivo puede ser utilizado para colocar código JavaScript que será ejecutado después de que la página sea leída WEB-INF/: liferay-look-and-feel.xml: Este archivo contiene las propiedades y metadata del tema (aquí también se definen los esquemas de color)
80 Themes Esquema de ColoresSe configuran en el archivo WEB-INF/liferay-look-and-feel.xml Ej.:
81 Themes Settings Cada tema puede definir un set de settings para hacerlo configurable. Los settings también se definen en el archivo WEB-INF/liferay-look-and-feel.xml, utilizando la siguiente sintáxis: Ej.: Estos settings pueden ser accesados en el template del tema usando el siguiente código:
82 Themes Settings Hay dos settings predefinidos que son leídos por el core de los portlets: portlet-setup-show-borders-default: Si está en false el portal quitará los bordes por defecto de todos los portlets bullet-style-options: El valor debe ser una lista separada por comas de estilos de bullets válidos a ser utilizados por el portlet de navegación , ej: dots,arrows,etc. Por defecto es una lista vacía, por lo tanto no se mostrará en la pantalla de configuración del portlet
83 Themes Variables PredefinidasObjetos de Contexto $theme_display: contiene información acerca del contexto del portal de la solicitud actual $portlet_display: Contiene información acerca del portlet actual, y está destinado a ser utilizado dentro de la plantilla portlet.vm $page: La página actual. El sitio actual puede ser obtenido usando $page.getGroup() $theme: Métodos utilitarios $serviceLocator: Permite invocar la capa de servicios de Liferay con el método findService(SERVICE_NAME) -> SERVICE_NAME es el class name del servicio
84 Themes Variables PredefinidasNavegación $nav_items: Contiene todas las páginas y puede ser iterado con #foreach Cada objeto tiene los siguientes métodos: isSelected(), getURL(), getTarget(), getName(), hasChildren(), getChildren() $sign_in_url, $sign_out_url
85 Themes Variables PredefinidasInformación de Usuario $user_greeting, $user_id, $user_ _address, $ user_name, $language_id, etc. Paths y URLs $css_folder, $images_folder, $javascript_folder, $company_logo, $company_url, etc. Macros #css(FILE_NAME): Crea un link HTML a CSS #js(FILE_NAME): Crea un elemento script HTML #language(FILE_NAME): Escribe un mensaje localizado con la clave dada
86 Themes Variables PredefinidasTambién es posible ver las definiciones de muchas más variables en los temas base de Liferay: [liferay-source]/portal-web/docroot/html/themes/_unstyled/templates/init.vm [liferay-source]/portal-web/docroot/html/themes/_unstyled/templates/init.ftl
87 Themes Embeber Portlets en TemasAlgunas veces es necesario embeber portlets en los temas, por ejemplo para poner un contenido web fijo en el footer de la página. Esto es hecho con la llamada al método: $theme.runtime() La parte importante a recordar es la diferencia entre portlets instanceables y portlets regulares: Portlets instanceables pueden aparecer múltiples veces en la misma página (Ej.: Web Content) Portlets no instanceables solo pueden ser agregados una sola vez a una página
88 Themes Embeber Portlets en TemasEmbeber Portlet No-Instanceable Se envía el portlet ID como parámetro. Ejemplo: Embeber Portlet Instanceable Se envía el portlet ID concatenado con la palabra INSTANCE, y un código random de cuatro letras (puede ser cualquiera, lo importante es que no se repita) Nota: Los portlets de Liferay están definidos en /ROOT/WEB-INF/portal-custom.xml , aquí se pueden ver los códigos.
89 Themes Agregar Estilos a Portlets y Layouts desde un TemaSe debe agregar un ID al layout, por ejemplo id=”blogColumn”, y en el CSS se puede decir que cualquier portlet dentro de esta columna tendrá un fondo azul con un código como el siguiente: Si se necesita agregar estilo a un cierto tipo de portlet, se debería hacer algo como lo siguiente: O también
90 Layout Templates Layout TemplatesSon utilizados para controlar cómo los portlets pueden ser ordenados en la página. Generalmente definen una estructura de grid. Son comúnmente creados con una combinación de Velocity, HTML y CSS. Son plugins hot deployables como los temas. También son creados mediante el Plugin’s SDK, y son almacenados en el subdirectorio layouttpl
91 Layout Templates Estructura del Layout Template:my-template.tpl: Template Velocity que genera la estructura HTML del template my-template.wap.tpl: Variante del template para dispositivos móviles my-template.png: Representación del template, será mostrado como preview WEB-INF/liferay-layout-templates.xml: Archivo de definición, aquí se configura el nombre del template y la locación de los archivos Es posible definir varios layout templates en un archivo Lo anterior es necesario en caso de querer crear múltiples layouts templates en un único proyecto de layouts
92 Layout Templates Estructura del Layout Template: Ejemplo:Todos los layouts deben tener al menos esta línea: $processor.processColumn("column-1");
93 Layout Templates Embebiendo Portlets en un Template Ejemplo:Portlet no instanceable (Search Portlet): Portlet instanceable (Navigation):
94 Layout Templates Tip: Para encontrar el portletID, podemos realizar las siguientes dos cosas: Agregar el portlet a la página e ingresar a Options > Look and Feel > Advanced > Styling En la base de datos, el portletId está en la tabla portletpreferences en el campo portletId
95 Hooks Fueron introducidos en Liferay 5.1 como una alternativa al enfoque Liferay Extension Environment (mucho menos eficiente) Ventajas: Son hot-deployables, por lo que los cambios son aplicados inmediatamente después del deploy Los cambios son removidos inmediatamente después de ser undeployado
96 Hooks Elementos Customizables: Cambios en configuraciónPersonalización de claves de lenguajes Sobrescritura de archivos JSP Indexación post procesamiento Proveer implementaciones personalizadas de servicios Creación de filtros de servlets Sobrescritura de Struts Actions
97 JSP Hooks Se pueden utilizar hooks para modificar JPSs existentes en el portal, o para crear nuevos. Los cambios son reversados cuando se undeploya el hook (mantiene una copia del jsp original) Se debe utilizar liferay-util:buffer para minimizar riesgos al modificar un JSP Lo primero es saber el portlet que queremos modificar, y después el JSP que queremos modificar Ejemplo, queremos modificar la página create_account.jsp del portlet “Sign In” para que el botón diga “Create” en vez de “Save”
98 JSP Hooks Primero creamos un plugin de tipo Hook, y luego creamos una nueva Hook Configuration, seleccionando el tipo “Custom JSPs”:
99 JSP Hooks En el wizard se debe seleccionar la página que se desea modificar:
100 JSP Hooks El archivo de configuración queda como el siguiente:Archivo JSP agregado al proyecto por el wizard:
101 JSP Hooks Al deployar el hook se crea una copia del archivo original:El JSP original podría incluirse si se desea, de esta forma:
102 JSP Hooks Maximizando la capacidad de actualización (Upgradability)Con el hook que se hizo, la cosa anda bien, pero si se actualiza Liferay, la página original podría cambiar, y esto afectaría al hook que se desarrolló, ya que se hizo sobre la versión antigua. La forma correcta es extender el JSP y no sobrescribirlo. Para lograr esto, se utiliza liferay-util:buffer
103 JSP Hooks Ejemplo:
104 JSP Hooks Application AdapterLos hooks afectan al portal entero. Desde Liferay 6.1, los JSP hooks pueden setear una configuración custom-jsp-global para permitir a los usuarios escoger en qué sitios queremos aplicar el hook de JSP. Por defecto el valor de
105 Language Hooks Liferay entrega la posibilidad de cambiar propiedades de mensajes del portal Creamos una nueva configuración de hook de tipo “Language properties”:
106 Language Hooks El archivo de configuraciones queda así:Se agregan con el wizard los archivos que vamos a configurar: El archivo de configuraciones queda así:
107 Service Layer Hooks Los hooks también pueden ser usados para sobrescribir implementaciones de cualquier método en un Servicio:
108 Service Layer Hooks Se selecciona el servicio que se quiere sobrescribir, y se crea la nueva clase:
109 Service Layer Hooks Se sobrescribe el método en la clase creada (sobrescribimos el método addValue(…)):
110 Service Layer Hooks Archivo de configuración actualizado:
111 Servlet Filter Hooks Podemos usar hooks para sobrescribir filtros o agregar nuevos:
112 Servlet Filter Hooks Implementación del filtro:
113 Struts Actions Hooks Los hooks también pueden ser usados para sobrescribir actions de Struts. Hay dos interfaces: Com.liferay.portal.kernel.struts.StrutsAction Usada para acciones regulares de Struts como /c/portal/update_password Com.liferay.portal.kernel.struts.StrutsPortletAction Usada por acciones de Struts que son usadas desde los portlets Ejemplo: Sobrescribir el Struts action para editar una Wiki Page
114 Struts Actions Hooks Creamos una página, le agregamos el portlet Wiki, y veamos su URL:
115 Struts Actions Hooks URL: p_p_id: Es el portlet name del Wiki p_p_lifecycle: Indica si la solicitud es un render, una action o un serveResource (fases del portlet) _36_struts_action: Es el Struts Mapping /wiki/edit_page definida en struts-config.xml
116 Struts Actions Hooks Los portlets del core de Liferay están definidos en el archivo: liferay-portal-
117 Struts Actions Hooks Las acciones de Struts de Liferay están definidas en el archivo: liferay-portal-
118 Struts Actions Hooks Clase implementadora: