Sunday, December 16, 2007

"Community Edition" quiere decir que no anda

Probando Liferay 4.3.5

Lo unico que queria era probar unos portlets JSR-168 que habia bajado de por ahi. Descargue Liferay Portal, lo configure para que use MySQL en lugar de HQL. Despues de un par de correcciones y problemas menores con Lucene (si tienen problemas de bloqueos borren los archivos generados y listo) pude hacer andar el puto portal. Bien, ahora era cuestion de crear usuarios, asignarlos a grupos, configurar sus roles, crear un par de paginas y tirar mis portlets.
Resulta que el portlet de administracion, con un usuario en rol administrador, no me deja hacer nada. No puedo crear locations, ni grupos de usuarios ni nada..y lo poco que puedo crear desaparece misteriosamente sin dejar rastro.
Fuck you Liferay...me voy a probar otra cosa. Cuando lo mas basico no funciona no vale la pena perder el tiempo dandole mas vueltas.

Avisen cuando saquen una version estable. Salu2

Tuesday, February 13, 2007

OSCache de OpenSymphony

Por si les paso y no saben que hacer.

Como obtener una unica instancia del GeneralCacheAdministrator (implementando un singleton)

import com.opensymphony.oscache.general.GeneralCacheAdministrator;

public class CacheAdmin {
private static GeneralCacheAdministrator theCacheAdmin = null;
private CacheAdmin(){
//
}
public static GeneralCacheAdministrator getInstance(){
if(theCacheAdmin == null){
theCacheAdmin = new GeneralCacheAdministrator();
}
return theCacheAdmin;
}
}

Despues, al momento de utilizarlo hacen:

GeneralCacheAdministrator admin = CacheAdmin.getInstance();

Monday, January 15, 2007

Portal, portlets y otras yerbas.

Buscando documentacion sobre Websphere Portal me tope con un articulo de IBM un poquito desactualizado. La nota comienza asi: "Ya sabemos que un portlet es un servlet...". En serio? No seria mejor decir "Un portlet ERA un servlet..". Antes de la JSR-168 (Portlet specification) un portlet era un servlet ya que la clase Portlet extendia a la clase Servlet. Desde la JSR-168 esto ya no es cierto, uno Portlet NO ES un Servlet. Si bien los conceptos son similares estaria bueno que los muchachos de IBM dejaran de publicar esas notas, salvo que, claro...las actualicen.

Wednesday, January 03, 2007

Midiendo tiempos...sin Annotations

Que pasa si no dispongo de Java 5.0 y no puedo hacer uso de las annotations? Bien, aca esta la solucion al ejemplo anterior pero sin anotaciones.
package com.miempresa.training.aop.advices;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class MiAOPTimer implements MethodInterceptor {
private static Log logger = LogFactory.getLog(MiAOPTimer.class);

public Object invoke(MethodInvocation methodInvocation) throws Throwable {
long t1 = System.currentTimeMillis();
Object retorno = methodInvocation.proceed();
long t2 = System.currentTimeMillis();
logger.info("Método:"+methodInvocation.getMethod().getName()+" ("+(t2-t1)+" ms)");
return retorno;
}
}

El primer cambio notorio es que ahora nuestro advice debe implementar una interfase y sobrescribir el metodo invoke, el resto del codigo queda igual.
Finalmente, nuestro archivo de configuracion de Spring queda de la siguiente forma:
<beans>
<aop:config>
<aop:advisor pointcut="execution(* com.miempresa.training..*.*(..))"
advice-ref="MiAOPTimer"/>
</aop:config>
<bean id="usuarioService" class=com.miempresa.training.aop.UsuarioServiceImpl"/>
<bean id="MiAOPTimer" class="com.miempresa.training.aop.advices.MiAOPTimer"/>
</beans>

Midiendo tiempos con Spring AOP

No hay nada mas facil que integrar AOP (Aspect Oriented Programming) con Spring. De hecho, Spring fue diseñado no para proveer la mejor solucion en AOP sino una forma sencilla de integrar aspectos en nuestras aplicaciones.
En este ejemplo quiero mostrar como se puede armar una rutina que mida el tiempo consumido por cada metodo sin llenar nuestro codigo de System.currentTimeMillis().

El primer paso es armar nuestro around advice:
package com.miempresa.training.aop.advices;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class MiAOPTimer {
private static Log logger = LogFactory.getLog(MiAOPTimer.class);

@Around("execution(* com.miempresa.training..*.*(..))")
public Object cronometro(ProceedingJoinPoint pjp) throws Throwable{
long t1 = System.currentTimeMillis();
Object retorno = pjp.proceed();
long t2 = System.currentTimeMillis();
logger.info("Método: "+pjp.getSignature().getName()+" (" + (t2-t1) + " ms)");
return retorno;
}
}

Basicamente lo que hace es ejecutar el metodo "cronometro" para cada metodo, de cualquier clase, bajo el paquete com.miempresa.training.El nombre del metodo puede ser cualquiera, solo debemos tener en cuanta que debe tomar un ProceedingJoinPoint como parametro, retornar un objeto e invocar al metodo proceed sobre el parametro.

El archivo de configuracion de Spring debe definir el advice y el tag de autoproxies.
<beans>
<bean id="usuarioService" class="com.miempresa.training.aop.ServicioImpl"/>
<aop:aspectj-autoproxy/>
<bean id="miAOPTimer" class="com.miempresa.training.aop.advices.MiAOPTimer"/>
</beans>