En el post Even MORE Performance fixes, me encontre con un nuevo feature muy interesante. Se trata de que cuando se inicia el TOMCAT se comprimen los javascript y css necesarios para obtener un mejor rendimiento de la carga del sitio en el cliente. ¿A que me refiero? A que genera los archivos ***_unpacked.css, ***_packed.css, ***_unpacked.js, ***_packed.js. Si bien no es complicado generar estos archivos, esta nueva funcionalidad simplica más el trabajo del desarrollador y mantiene siempre los archivos comprimos actualizados.
Comprimir JS y CSS en el inicio del Tomcat
January 29th, 2009Aplicaciones web para el IPhone dentro de Liferay
January 29th, 2009Al leer el post Laverage IPhone web applications within Liferay, pense que cuando se accede a un sitio que tenga Liferay desde un IPhone el layout de la pagina se ajustaria a la pantalla del IPhone como pasa cuando se accede desde un celular mediante WAP. El post simplemente habla de utilizar aplicaciones web de terceros como facebook, digg, twitter, entre otras; dentro de un iframe. Considero que esto no aporta absolutamente nada de nuevo a Liferay.
¿Alguien accedio desde un IPhone a un sitio de Liferay? ¿Este sitio se muestra como si fuera WAP? ¿O se muestra en forma normal? Haciendo un analisis sin realizar una prueba (porque no tengo el IPhone) creo que se mostraria como una página normal, aunque considero que la página deberia ajustarse a la pantalla del IPhone como funcionan estas aplicaciones web que mencionamos anteriormente, esto serviria para una mejor navegación del sitio.
PortletURL en JavaScript
December 22nd, 2008Una funcionalidad que acabo de descubrir en el Blog de Liferay es crear el PortletUrl en JavaScript.
Un ejemplo de PortletUrl es:
http://localhost:8080/web/guest/home?p_p_id=EDITAR_CUENTA&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&_EDITAR_CUENTA_struts_action=%2Feditar_cuenta%2Fview
Aca le estoy pasando el portlet id, el estado del portlet, la fase del ciclo de vida, la acción de struts a ejecutar y 1 parametro (podrian ser muchos más). Anteriormente la manipulación de esta url era medio complicada, ya que solo se podia generar a traves de JAVA o mediante una concatenación kilometrica de varios strings. Con esta funcion nos proporciona mayor flexibilidad a la hora de programar.
<script type=”text/javascript”>
var portletURL = new Liferay.PortletURL(_PHASE);
portletURL.setParameter(“key1″, “value”);
portletURL.setParameter(“key2″, “value”);
portletURL.setPortletId(_PORTLET_ID);
</script>
<a href=”javascript: portletURL.toString()”>Go to</a>
Los valores que puede tomar _PHASE son:
- ACTION_PHASE
- RENDER_PHASE
- RESOURCE_PHASE
También existen los siguientes métodos que permiten crear el PortletUrl según _PHASE:
- Liferay.PortletURL.createActionURL();
- Liferay.PortletURL.createRenderURL();
- Liferay.PortletURL.createResourceURL();
Estos son los métodos restantes de la clase Liferay.PortletURL:
- setCopyCurrentRenderParameters: function(copyCurrentRenderParameters);
- setDoAsUserId: function(doAsUserId);
- setEncrypt: function(encrypt);
- setEscapeXML: function(escapeXML);
- setLifecycle: function(lifecycle);
- setName: function(name);
- setParameter: function(key, value);
- setPlid: function(plid);
- setPortletConfiguration: function(portletConfiguration);
- setPortletId: function(portletId);
- setPortletMode: function(portletMode);
- setResourceId: function(resourceId);
- setSecure: function(secure);
- setWindowState: function(windowState);
- toString: function();
Crear una comunidad
November 20th, 2008A continuación esta el codigo que nos permite crear una comunidad a partir de una comunidad existente,
Obtener comunidad template
Group templateGroup = GroupLocalServiceUtil.getGroupByFriendlyUrl(“/template”);
Crear una comunidad
String name = ParamUtil.getString(actionRequest, “name”);
String description = ParamUtil.getString(actionRequest, “description”);
String friendlyURL = ParamUtil.getString(actionRequest, “friendlyURL”);
Group newGroup = GroupServiceUtil.addGroup(name, description,
GroupImpl.TYPE_COMMUNITY_PRIVATE, StringPool.BLANK, true);
Copiar la configuración del LayoutSet
LayoutSet publicLayoutSet = LayoutSetLocalServiceUtil.getLayoutSet(templateGroup.getGroupId(), false);
LayoutSetServiceUtil.updateLookAndFeel(newGroup.getGroupId(),
false, publicLayoutSet.getThemeId(), publicLayoutSet
.getColorSchemeId(), publicLayoutSet.getCss(),
false);
LayoutSetServiceUtil.updateLookAndFeel(newGroup.getGroupId(),
false, publicLayoutSet.getWapThemeId(), publicLayoutSet
.getWapColorSchemeId(), StringPool.BLANK, true);
LayoutSet privateLayoutSet = LayoutSetLocalServiceUtil.getLayoutSet(templateGroup.getGroupId(), false);
LayoutSetServiceUtil.updateLookAndFeel(newGroup.getGroupId(),
false, privateLayoutSet.getThemeId(), privateLayoutSet
.getColorSchemeId(), privateLayoutSet.getCss(),
false);
LayoutSetServiceUtil.updateLookAndFeel(newGroup.getGroupId(),
false, privateLayoutSet.getWapThemeId(), privateLayoutSet
.getWapColorSchemeId(), StringPool.BLANK, true);
Definir que copiar
Map<String, String[]> parameterMap = new HashMap<String, String[]>();
parameterMap.put(PortletDataHandlerKeys.PERMISSIONS,
new String[] { Boolean.TRUE.toString() });
parameterMap.put(PortletDataHandlerKeys.USER_PERMISSIONS,
new String[] { Boolean.TRUE.toString() });
parameterMap.put(PortletDataHandlerKeys.PORTLET_DATA,
new String[] { Boolean.TRUE.toString() });
parameterMap.put(PortletDataHandlerKeys.PORTLET_SETUP,
new String[] { Boolean.TRUE.toString() });
parameterMap.put(PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS,
new String[] { Boolean.TRUE.toString() });
parameterMap.put(PortletDataHandlerKeys.PORTLET_USER_PREFERENCES,
new String[] { Boolean.TRUE.toString() });
parameterMap.put(PortletDataHandlerKeys.THEME,
new String[] { Boolean.TRUE.toString() });
Exportar datos de la comunidad template
byte[] publicOriginalGroup = LayoutServiceUtil.exportLayouts(
templateGroupId, false, parameterMap, null, null);
byte[] privateOriginalGroup = LayoutServiceUtil.exportLayouts(
templateGroupId, true, parameterMap, null, null);
Importar datos a la nueva comunidad
LayoutServiceUtil.importLayouts(newGroup.getGroupId(), false,
parameterMap, publicOriginalGroup);
LayoutServiceUtil.importLayouts(newGroup.getGroupId(), true,
parameterMap, privateOriginalGroup);
Portlet de sistema
November 19th, 2008En varias ocasiones tuve el requerimiento de no mostrar algunos portlets en la lista de portlets disponibles para ser agregados a una página, y este ocultamiento no se podia hacer mediante permisos porque el usuario tenia que usar el portlet y no debia tirar el error de que el portlet no estaba disponibles. Entonces me di cuenta de que algunos portlets del core de Liferay no estaban disponibles para ser agregados a una página, por ejemplo el portlet de Look and Feel, el My Account o el del Page Setting. Para esto hay que declarar al portlet como portlet de sistema en liferay-portlet.xml.
liferay-portlet.xml
<portlet>
<portlet-name>MIPORTLET</portlet-name>
…
<system>true</system>
</portlet>
Desde otro portlet vamos a llamar a MIPORTLET
<%
PortletURL miPortletURL = new PortletURLImpl(
request, “MIPORTLET”, plid, PortletRequest.ACTION_PHASE);
miPortletURL.setWindowState(WindowState.MAXIMIZED);
miPortletURL.setPortletMode(PortletMode.VIEW);
miPortletURL.setParameter(“struts_action”, “/miportlet/view”);
%>
<a href=”<%= miPortletURL %>”>IR A MI PORTLET</a>
Mostrar un portlet en un PopUp
November 12th, 2008Armo la URL
<portlet:renderURL windowState=”<%= LiferayWindowState.EXCLUSIVE.toString() %>” var=”url”>
<portlet:param name=”struts_action” value=”/miportlet/popupview” />
</portlet:actionURL>
Llamo al POPUP
<script type=”text/javascript”>
function mostrar_popup() {
var _dialog = Liferay.Popup( {
width: 700,
modal: true,
message: ‘<div class=”loading-animation” />’,
position: ['center', 100],
title: <liferay-ui:message key”popup-title”/>,
resizable: false,
draggable: false,
onClose: function() {
// se ejecuta cuando el portle se cierra
}
} );
jQuery.ajax( {
url: “<%= url %>”,
success: function(message) {
_dialog.html(message);
}
} );
}
</script>
<a href=”javascript:mostrar_popup();”>mostrar popup</a>
Al definir el estado de la ventana como exclusivo, el resultado de la respuesta solamente va a ser el contenido del portlet al cual se invoca.
Ejemplo:
Agregar portlets en un Layout en tiempo de ejecución
November 11th, 2008A veces, cuando el diseño del sitio es complejo, necesitamos agregar a una página un portlet en determinado lugar del sitio fuera del contendor de portlets, o simplemente queremos agregar un portlet y que aparezca en todas las paginas que utilicen este layout, y que nadie lo pueda mover o cerrar.
Para esto, y a partir de la version 4.3.x de Liferay, tenemos la posibilidad de agregar portlets en tiempo de ejecución en los archivos .tpl que definen los layouts disponibles en el sitio (ubicados en la carpeta “layouttpl”)
Simplemente agregamos esta linea:
$processor.processPortlet("71")
donde 71 es el Id del portlet que quiero agregar.
Entonces un template común, en este caso (30/70) se veria así:
<table id="layout-grid">
<tr>
<td class="lfr-column thirty" id="left" valign="top">
$processor.processPortlet("71")
$processor.processColumn("left")
</td>
<td class="lfr-column seventy" id="column-1" valign="top">
$processor.processPortlet("73")
$processor.processColumn("column-1")
</td>
</tr>
</table>
y en este layout el portlet de navegación (id = 71) y el breadcrumb (id = 73) estarían fijos en todas las paginas que usen este layout por encima del contenedor de portlets de cada columna.
Redirigir a una página despúes de registrarse
November 11th, 2008Para redirigir a una página de una comunidad después de registrarse en Liferay, hay que agregar un Evento, entonces vamos a hacer lo siguiente:
portal-ext.properties
login.events.post=com.liferay.portal.events.MyLoginPostAction,\
com.liferay.portal.events.DefaultLandingPageAction
MyLoginPostAction.java
package com.liferay.portal.events;
import ….
public class MyLoginPostAction extends Action {
private static Log _log = LogFactory.getLog(MyLoginPostAction.class);
public void run(HttpServletRequest req, HttpServletResponse res) throws ActionException {
try {
Group group = this.getGroup(req);
this.setLastPath(group, req);
} catch(Exception e) {
_log.error(e);
throw new ActionException(e);
}
}
private void getGroup(HttpServletRequest req) {
return null;
}
private void setLastPath(Group group, HttpServletRequest req)
throws PortalException, SystemException {
long defaultPlid = LayoutLocalServiceUtil.getDefaultPlid(group.getGroupId());
Layout defaultLayout = LayoutLocalServiceUtil.getLayout(defaultPlid);
HttpSession ses = req.getSession();
Map<String, String[]> params = new HashMap<String, String[]>();
params.put(“p_l_id”, new String[] { Long.toString(defaultLayout.getPlid()) });
LastPath lastPath = new LastPath(“/c”, “/portal/layout”, params);
ses.setAttribute(WebKeys.LAST_PATH, lastPath);
}
}
En este caso va a redirigir a la primer página publica de la comunidad y si esta no existe la redirige a la primer página privada.
Esto también puede ser para redirigir a una organización o a la página de un usuario.
Configurar las preferencias de los Portlets
November 10th, 2008En primer lugar vamos a crear un portlet con el Plugin SDK y luego vamos a editar el archivo $SDK_HOME/docroot/WEB-INF/portlet.xml.
En este caso vamos a ver la configuración del Portlet RSS para tener un ejemplo concreto para ver, luego de agregar las propiedades vamos a ver como obtenemos dichos valores.
<portlet>
<portlet-name>RSS</portlet-name>
<display-name>RSS</display-name>
<portlet-class>com.liferay.portlet.StrutsPortlet</portlet-class>
<init-param>
<name>view-action</name>
<value>/rss/view</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
</supports>
<resource-bundle>com.liferay.portlet.StrutsResourceBundle</resource-bundle>
<portlet-preferences>
<preference>
<name>urls</name>
<value>http://rss.news.yahoo.com/rss/tech</value>
<value>http://csmonitor.com/rss/scitech.rss</value>
<value>http://partners.userland.com/nytRss/technology.xml</value>
</preference>
<preference>
<name>items-per-channel</name>
<value>2</value>
</preference>
</portlet-preferences>
<security-role-ref>
<role-name>power-user</role-name>
</security-role-ref>
<security-role-ref>
<role-name>user</role-name>
</security-role-ref>
</portlet>
En ese caso hemos creado 2 preferencias, urls y items-per-channel.
Para obener estos valores hay que hacer:
PortletPreferences porttletPreferences = renderRequest.getPortletPreferences();
String[] urls = porttletPreferences.getValues(“urls”, new String[]());
long ipc = GetterUtil.getLong(portletPreferences.getValue(“items-per-channel”));
Antes de comenzar
November 9th, 2008Antes de comenzar con Liferay, voy a hacer un resumen de las propiedades más importantes
portal-ext.properties
# El nombre de la compañia por default
company.default.web.id=miproyecto.com
# Especifica como el usuario puede loguearse al sistema
# Valores que puede tomar esta propiedad: emailAddress, screenName, userId
company.security.auth.type=emailAddress
# Permite si un usuario no logueado puede crear o no una cuenta
company.security.strangers=true
# Locales disponibles
locales=es_ES
# Si esta propiedad esta en true, un usuario invitado toma como por default el lenguaje de la aplicacion.
# Caso contrario toma el valor de header del request.
locale.default.request=false
# Los Time Zones disponibles
time.zones=America/Buenos_aires
# Directorio donde Liferay guardar los indices de Lucene, los archivos de Document Library, Jackrabbit, etc.
resource.repositories.root=${user.home}/liferay/miproyecto
# Si esta propiedad esta en true, carga todo el css en un archivo comprimido (SUPER RECOMENDADO)
theme.css.fast.load=true
# Si esta propiedad esta en true, carga todo el javascript en un archivo comprimido (SUPER RECOMENDADO)
javascript.fast.load=true
system-ext.properties
#País y Lenguaje predeterminado
user.country=AR
user.language=es
# Time Zone predeterminado
user.timezone=GMT
