Axelhzf

Feb 04

Ampliando el módulo de Google Guice

Como comenté al final de mi post anterior mi intención era añadir al módulo de play las clases que añaden el scope LazySingleton.

Los cambios están en este commit.

Añadí a la clase GuiceSupport una variable con el stage en función del modo en el que se está ejecutando play y creé la clase PlayAbstractModule que incluye el método bindLazySingletonOnDev.

Para utilizarlo:

conf/dependencies.yml

require:
    - play
    - axelhzf -> guice 1.3

repositories:
    - axelhzf-guice-repository:
        type: http
        artifact: "http://cloud.github.com/downloads/axelhzf/play-guice-module/guice-[revision].zip"
        contains:
            - axelhzf -> guice

Configuración del inyector

public class GuiceConfig extends GuiceSupport {
    @Override
    protected Injector configure() {
        return Guice.createInjector(stage, new PlayAbstractModule() {
            @Override
            protected void configure() {                
                bindLazySingletonOnDev(MyService.class, MyServiceImpl.class);
                bindLazySingletonOnDev(MyDependentService.class, MyDependentServiceImpl.class);
            }
        });
    }
}

Feb 02

Play Framework + Google Guice

En el proyecto en el que estoy trabajando actualmente empezamos a utilizar Google Guice. Para quien no lo sepa, Guice es un framework de inyección de dependencias. La idea básica de la inyección de dependencias consiste en sumistrar a una clase sus dependencias, en lugar de que sea esta quien tenga que instanciarlas.

Play cuenta con un módulo para integrar Guice:

http://www.playframework.org/modules/guice-1.2/home

Además de la propia documentación del módulo, está este post de @_felipera que te puede ayudar a dar los primeros pasos:

http://geeks.aretotally.in/dependency-injection-with-play-framework-and-google-guice

Los pasos para empezar a utilizar Guice en tu proyecto play son:

services.MyService

package services;
public interface MyService {
    public void sayHello();
}

services.MyServiceImpl

package services;
public class MyServiceImpl implements MyService {
    public MyServiceImpl(){
        play.Logger.info("Constructor!");
    }
    @Override
    public void sayHello() {
        play.Logger.info("hello");
    }
}

De esta forma se configura la clase como un singleton. Cada vez que una clase tenga la dependencia de MyService se inyectará la misma instancia de MyServiceImpl.

Ya con esto está el servicio inyectado en el controlador.

Mi siguiente paso fue crear un test y es aquí cuando me encontré una sorpresa:

play test

http://localhost:9000/@tests

Compilation error! El problema está en que el módulo tiene una carpeta que se llama test. Esta carpeta en vez de tener algunos tests unitarios o funcionales, lo que tiene son 3 aplicaciones de ejemplo. Lo normal hubiera sido seguir la convención de play que es poner este tipo de aplicaciones en la carpeta ‘samples-and-tests’.

Hice un fork del proyeto para renombrar esta carpeta

https://github.com/axelhzf/play-guice-module

También hice un pull-request, pero no he tenido respuesta :(

https://github.com/pk11/play-guice-module/pull/5

Renombrando la carpeta test del módulo sería suficiente para poder ejecutar este test:

@InjectSupport
public class InjectTest extends UnitTest {
    @Inject
    static MyService myService;

    @Test
    public void injectOk(){
        assertNotNull(myService);
    }       
}

Por defecto play detecta automáticamente la anotaciones @Inject en las clases que hereden de Controller, Job and Mail. Si queremos poder inyectar dependencias en otras clases debemos anotar la clase con @InjectSupport.

Normalmente nuestros servicios no son tan simples como MyService. Lo normal es tener dependencias entre servicios. Guice resuelve esto analizando las dependencias e instanciando los objetos en el orden adecuado.

services.MyDependentServicee

package services;

public interface MyDependentService {
    public void sayHelloWorld();
}

service.MyDependenServiceImpl

package services;

@InjectSupport
public class MyDependentServiceImpl implements MyDependentService {

    @Inject
    static MyService myService;

    public MyDependentServiceImpl(){
        play.Logger.info("Inicializando MyDependentServiceImpl");
    }

    public void sayHelloWorld(){
        myService.sayHello();
        play.Logger.info("world");
    }       
}

InjectTest

@InjectSupport
public class InjectTest extends UnitTest {

    @Inject
    static MyDependentService myDependentService;

    @Test
    public void injectOk(){
        assertNotNull(myDependentService);
        myDependentService.sayHelloWorld();
    }

}

Incluimos el binding

 bind(MyDependentService.class).to(MyDependentServiceImpl.class).in(Singleton.class);

Y esta es la salida por la consola

20:34:39,090 INFO  ~ Inicializando MyServiceImpl
20:34:39,095 INFO  ~ Inicializando MyDependentServiceImpl
20:34:39,095 INFO  ~ Application 'lazySingleton' is now started !
20:34:39,136 INFO  ~ hello
20:34:39,136 INFO  ~ world

Se inicializa primero MyService y luego MyDependentService

Una de las cosas que no me gusta del módulo es que te limita a que los campos que puedes inyectar deben de ser estáticos. Las dependencias por ejemplo me gustaría poder definirlas como parámetros en el constructor. De forma que quede claro que para crear un objeto de la clase MyDependentServiceImpl hace falta un objeto del tipo MyService. Además, utilizar las dependencias mediante constructor facilita hacer tests unitarios.Únicamente es necesario llamar al constructor y pasar como parámetros stubs o mocks de las dependencias. De esta forma no estamos obligados a configurar un inyector.

En la documentación del módulo no vi ninguna referencia a cómo hacer esto. Encontré un artículo que explicaba cómo hacerlo utilizando un Provider:

http://ericlefevre.net/wordpress/2011/05/08/play-framework-and-guice-use-providers-in-guice-modules/

Esta forma funciona correctamente pero más tarde encontré una pregunta en stackoverflow que me dio otra pista:

http://stackoverflow.com/questions/8435686/does-injector-getinstance-always-call-a-constructor

En el Edit pone que se olvidó de anotar con @Inject el constructor. Probé a hacer lo mismo y funcionó:

public class MyDependentServiceImpl implements MyDependentService {

    private final MyService myService;

    @Inject
    public MyDependentServiceImpl(MyService myService){
        this.myService = myService;
        play.Logger.info("Inicializando MyDependentServiceImpl");
    }
    ….

Me faltaba un pequeño detalle para tener google guice configurado perfectamente. En el log se puede ver como los servicios se inicializan cuando se inicia la aplicación.

21:38:11,801 INFO  ~ Inicializando MyServiceImpl
21:38:11,805 INFO  ~ Inicializando MyDependentServiceImpl
21:38:11,805 INFO  ~ Application 'lazySingleton' is now started !

Cuando la aplicación está en modo producción está bien, es el comportamiento adecuado. Los servicios se deberían instanciar al arrancar la aplicación. Pero cuando estoy en modo desarrollo prefiero que los Singletons se inicialicen bajo demanda (lazy). Puede que haya servicios que tarden en iniciarse y quiero que el tiempo que tarda la aplicación en arrancar en modo desarrollo sea lo más rápido posible.

Buscando en la documentación de google guice veo que está preparado para hacer justamente lo que quiero:

http://code.google.com/p/google-guice/wiki/Scopes

Lo único que hay que hacer es que configurar es el STAGE para indicarle a Guice si estamos en modo desarrollo o en modo producción:

    Stage stage = Play.mode.isDev()?Stage.DEVELOPMENT : Stage.PRODUCTION;
    return Guice.createInjector(stage, new AbstractModule() {…..

Al volver a ejecutar el test

22:00:03,353 WARN  ~ You're running Play! in DEV mode
22:00:04,615 INFO  ~ Connected to jdbc:h2:mem:play;MODE=MYSQL;LOCK_MODE=0
22:00:04,811 INFO  ~ Guice injector created: config.GuiceConfig
22:00:04,819 INFO  ~ Inicializando MyServiceImpl
22:00:04,824 INFO  ~ Inicializando MyDependentServiceImpl
22:00:04,824 INFO  ~ Application 'lazySingleton' is now started !

Vaya, se volvieron a instanciar los singletons al iniciar la aplicación. ¿Será que el Stage no sirve para lo que creo? Vamos a probar con un test:

public class StageTest {

    @Test
    public void testDevelopment(){
        Injector injector = createInjector(Stage.DEVELOPMENT);
        System.out.println("development - antes del getInstance");
        MyService instance = injector.getInstance(MyService.class);
        System.out.println("development - después del getInstance");
    }

    @Test
    public void testProduction(){
        Injector injector = createInjector(Stage.PRODUCTION);
        System.out.println("production - antes del getInstance");
        MyService instance = injector.getInstance(MyService.class);
        System.out.println("production - después del getInstance");
    }

    public Injector createInjector(Stage stage){
        Injector injector = Guice.createInjector(stage, new AbstractModule(){
            @Override
            protected void configure() {
                bind(MyService.class).to(MyServiceImpl.class);
            }
        });
        return injector;
    }
}

Y el resultado es:

INFO: development - antes del getInstance
INFO: Inicializando MyServiceImpl
INFO: development - después del getInstance

INFO: Inicializando MyServiceImpl
INFO: production - antes del getInstance
INFO: production - después del getInstance

Como pone en la documentación, cuando se está en modo DEVELOPMENT los Singleton se inicializan de forma lazy.

¿Si esto funciona así, por qué cuando lo probé con el módulo de play no funcionó?

Revisando el código:

https://github.com/pk11/play-guice-module/blob/master/src/play/modules/guice/GuicePlugin.java

Encontré que lo que se hace en el @OnApplicationStart es buscar todas las clases que están anotadas con @InjectSupport las dependencias. Para inyectarlas hace un getBean de cada una. Aquí esta el problema, al hacer el getBean se instancia.

Buscando en internet encontré una solución a este problema:

https://groups.google.com/d/msg/google-guice/405HVgnCzsQ/fBUuueP6NfsJ

El código para permitir LazySingleton

Estas clases lo que hacen es que cuando se crea el inyector, crea un proxy para cada una de las clases que están anotadas como @LazySingleton. De forma que cuando inyecta los objetos lo que se inyecta en realidad es el proxy. La primera vez que se invoque un método de alguna de estas clases, el proxy se va a encargar de inicializar la clase.

La configuración del inyector quedaría así:

public class GuiceConfig extends GuiceSupport {
    @Override
    protected Injector configure() {
        Stage stage = Play.mode.isDev() ? Stage.DEVELOPMENT : Stage.PRODUCTION;
        return Guice.createInjector(stage, new AbstractModule() {
            @Override
            protected void configure() {    
                bindScope(LazySingleton.class, MoreScopes.LAZY_SINGLETON);
                bindLazySingletonOnDev(MyService.class, MyServiceImpl.class);
                bindLazySingletonOnDev(MyDependentService.class, MyDependentServiceImpl.class);
            }

            protected <T> void bindLazySingletonOnDev(Class<T> expected, Class<? extends T> implClass){
                if(Play.mode.isDev()){
                    bind(implClass).in(MoreScopes.LAZY_SINGLETON);
                    Provider<T> provider = LazyBinder.newLazyProvider(expected, implClass);
                    bind(expected).toProvider(provider);
                }else{
                    bind(expected).to(implClass).in(Scopes.SINGLETON);
                }
            }
        });
    }
}

Cuando la aplicación está en modo desarrollo, las clases se instanciarán la primera vez que se llame a un método. Cuando usemos el modo producción, las clases se instanciarán cuando se inicie la aplicación.

Me queda pendiente añadir estas clases al fork para poder tener un módulo completo que se pueda reutilizar en todos los proyectos.

Sep 26

Knockout.js (Ejemplo completo)

En el anterior post hice un pequeña introducción a la librería knockout.js. Este post, continuación del anterior, tiene un ejemplo más completo en el cual espero que se vea mejor la utilidad de la librería. En el ejemplo crearemos una tabla de Posts, donde mostraremos el título y el texto. Le añadiremos a la tabla filtrado y edición inline. Con esto veremos cómo utilizar variables observables, dependentObservables y observableArrays. También haremos uso de jquery tmpl para renderizar la vista.

Este post también forma parte del curso de desarrollo de aplicaciones web con Play.

Prueba el ejemplo completo en http://jsfiddle.net/9mSBY/

Esqueleto de la página

Enlazamos los css y js que vamos a utilizar:

Tabla

Añadimos la tabla donde mostraremos el listado de Post en 3 columnas. La primera de selección, la segunda el título y luego el texto.

<div class="container">
    <table>
        <thead>
        <tr>
            <th></th>
            <th>Title</th>
            <th>Text</th>
        </tr>
        </thead>
        <tbody />
    </table>
</div>

ViewModel

El viewModel contará con un listado de post que se mostrarán en la tabla

<script>
     function containsIgnoreCase(s, q){
        return s.toLowerCase().indexOf(q.toLowerCase()) != -1;
     }

     function Post(title, text){
        this.title = ko.observable(title);
        this.text = ko.observable(text);
        this.selected = ko.observable(false);

        this.containsText = function(query){
            return containsIgnoreCase(this.title(), query)
                || containsIgnoreCase(this.text(), query);
        }
     }

     var viewModel = {
        posts : ko.observableArray([])
     }

     viewModel.posts.push(new Post('title1', 'text1'));
     viewModel.posts.push(new Post('title2', 'text2'));

     ko.applyBindings(viewModel);
</script>

En la clase Post se han definido los 3 campos como variables observables, para que los cambios que se hagan en esas variables se actualicen automáticamente. En el viewModel hemos definido un observableArray con el listado de post. Añadimos a esta lista dos posts de ejemplo.

Para mostrar los posts en la tabla. Creamos una nueva plantilla que mostrará el contenido de cada fila.

<script type="text/html" id="postRow">
    <tr>
        <td><input type="checkbox" data-bind="checked: selected" /></td>
        <td>${title}</td>
        <td>${text}</td>
    </tr>
</script>

Y añadimos en binding en la tabla para que renderice la plantilla “postRow” con el listado de “posts”.

<tbody data-bind="template : {name : 'postRow', foreach: posts}" />

Con este código ya tenemos sincronizada la tabla con la lista de Posts. Para hacer una prueba podemos abrir la consola javascript y añadir un nuevos post.

viewModel.posts.push(new Post('prueba', 'desde la consola de javascript!');

La tabla se tiene que haber actualizado automáticamanete con la nueva fila añadida.

Filtrado

Para añadir filtrado de la tabla vamos a almacenar dos arrays, uno con la lista de posts completos y otro con la lista de posts filtrados.

Añadimos un campo de texto donde vamos a escribir el filtro. El evento por defecto que actualiza el viewModel es cuando pierde foco. Para hacer un filtrado en tiempo real podemos cambiar el evento de actualización a ‘afterkeydown’.

<div class="container">
    ...

    <form>
    <div class="clearfix">
        <input class="xxlarge" type="text" data-bind="value : filterQuery, valueUpdate:'afterkeydown'" placeholder="Filter"/>
    </div>
    </form>
</div>

Modificamos el viewModel para añadir el texto por el que se filtra y la lista de posts filtrados. Definimos la variable filteredPost como dependentObservable, de esta forma, cada vez que se actualice la lista de post, se volverá a evaluar la lista de post filtrados. En el caso de que el filtro esté vacio, mostramos la lista de todos los posts.

var viewModel = {
    posts : ko.observableArray([]),
    filterQuery : ko.observable('')
}

viewModel.filteredPosts = ko.dependentObservable(function(){
    var query = this.filterQuery();
    if(query){
        var filtered = [];
        $.each(viewModel.posts(), function(i, post){
            if(post.containsText(query)){
                filtered.push(post);
            }
        });
        return filtered;
    }
    //Not filtering
    return viewModel.posts();
}, viewModel);

Modificamos el binding de la tabla para mostrar la lista de posts filtrados.

<tbody data-bind="template : {name : 'postRow', foreach: filteredPosts}" />

Edición inline

Para permitir la edición inline vamos a añadir una nueva variable que nos indique si estamos en modo edición. En el modo de edición, en la tabla aparecerán campos de texto donde el usuario podrá modificar las filas. También añadiremos un botón de nuevo y un botón para borrar las filas seleccionados.

Botones para realizar las acciones.

<div class="container">
    ...

    <form>
    <div class="clearfix">
            <a href="#" class="btn primary" data-bind="click : newPost">New post</a>
            <a href="#" class="btn primary" data-bind="visible: editMode, click: toggleEditMode">Save</a>
            <a href="#" class="btn" data-bind="visible: !editMode(), click : toggleEditMode">Edit</a>
            <a href="#" class="btn danger" data-bind="click : deletePosts">Delete</a>
    </div>
     ...

La plantilla muestra el texto o un input dependiendo del campo editMode.

<script type="text/html" id="postRow">
    <tr>
        <td><input type="checkbox" data-bind="checked: selected" /></td>
        {{if viewModel.editMode()}}
            <td><input type="text" data-bind="value : title" /></td>
            <td><input type="text" data-bind="value : text" /></td>
        {{else}}
            <td>${title}</td>
            <td>${text}</td>
        {{/if}}
    </tr>
</script>

Añadimos las acciones al modelo.

var viewModel = {
    posts : ko.observableArray([]),
    filterQuery : ko.observable(''),
    editMode : ko.observable(false)
}

viewModel.selectedPosts = ko.dependentObservable(function(){
    var result = [];
    $.each(this.posts(), function(i, post){
        if(post.selected()){
            result.push(post);
        }
    });
    return result;
}, viewModel);

viewModel.toggleEditMode = function(){
    viewModel.editMode(!viewModel.editMode());
}

viewModel.newPost = function(){
    viewModel.posts.push(new Post('',''));
    viewModel.editMode(true);
}

viewModel.deletePosts = function(){
    viewModel.posts.removeAll(viewModel.selectedPosts());
}

Declarando la variable selectedPosts como dependentObservable nos aseguramos que esté sincronizada con la lista de posts. A la hora de borrar los posts de la lista utilizamos la función removeAll y le pasamos la lista completa de posts seleccionados.

Conclusiones

En el ejemplo hemos visto como podemos utilizar knockout.js para tener sincronizada la interfaz de usuario con el modelo. Haciendo uso de variables dependientes y bindings hemos conseguido darle comportamiento dinámico a una tabla estática. En pocas lineas de código hemos conseguido que nuestra tabla sea completamente editable y filtrable.

Falta ver como sincronizar nuestro modelo con el servidor por medio de llamadas ajax. Lo dejo pendiente para un futuro artículo.

Puedes ver el código completo en http://jsfiddle.net/9mSBY/

Sep 25

Knockout.js

knockout.js es una librería javascript que implementa el patrón Model View View-Model.

Patrón Model View View-Model

Patrón Model View View-Model (MVVM) es un patrón diseñado para construir interfaces de usuario. Describe cómo mantener de una forma simple una interfaz de usuario sofisticada dividiéndola en tres partes:

Aplicado a Knockout.js

Ejemplo

http://jsfiddle.net/h7tgN/

En el ejemplo tenemos un campo de texto donde estamos escribiendo en la variable valor. La variable se esta actualizando automáticamente cuando se presiona una tecla. Después tenemos una etiqueta span donde estamos mostrando el contenido de la variable. Vemos que a medida que vamos escribiendo en el campo de texto se va actualizando la etiqueta.

Recomiendo que pruebes los tutoriales de knockout.js http://learn.knockoutjs.com/. Están bastante trabajados y tienen una web donde puedes ir probando el código en la página web directamente y viendo los resultados.

Nota : El contenido de este post pertenece a un curso de desarrollo de aplicaciones web con Play Framework que daré del 3 al 7 de octubre.

Sep 10

Vim dentro de Eclipse

A raíz de un artículo “Learn Vim Progressively" recordé la potencia que tenía vim y los tiempos en los que lo utilizaba a diario (esos tiempos donde no dejaban utilizar un IDE para las prácticas de la universidad). El problema es que ahora me he vuelto IDEdependiente y en concreto Eclipse dependiente (aunque a esto último le intento poner remedio: Idea? ;)

Así que buscando un poco por internet llegue como suele ser habitual a StackOverflow donde recomendaban una serie de plugins para simular algunas características de vim dentro de Eclipse. Me decidí por Viable (me pareció la opción más viable, jojojo)

El plugin es de pago, pero bueno, es Java, no hay que ser ningún crack para hacerle un apaño.

Jun 27

Access DB manager from the PlayFramework

Jun 19

Creando una presentación con HTML+CSS+JS

Me encanta la presentación html5rocks. Es interactiva, puedes ir probando todo lo que va explicando. Incluso dibujar un Doraemon en la diapositiva 47. Lo mejor de todo es que crearon un generador de diapositivas y nosotros mismos podemos crear diapositivas de este tipo.

Proyecto

El proyecto se llama landslide y se puede descargar de https://github.com/n1k0/landslide

Instalación

En la página principal están las instrucciones de instalación. Hay varias opciones, la que yo seguí fue clonar el repositorio e instalar

git clone git://github.com/n1k0/landslide.git
cd landslide
python setup.py build
sudo python setup.py install

Creando la presentación

Las presentaciones se escriben con markdown. Este formato se está popularizando bastante, por ejemplo tumblr ya tiene soporte y es el formato con el que estoy escribiendo el post.

Creamos un fichero con extensión .md, presentacion.md

# Título de la presentación
---
## Primera diapositiva

Contenido de la diapositiva

---
## Segunda diapositiva

Contenido de la **segunda** diapositiva

Esta es una presentación bastante simple. Cada diapositiva va separada con —- y el título de la diapositiva con ##

Compilando la presentación

Para poder ver la presentación tenemos que compilarla para que se cree el html.

landslide presentacion.md 

Esto genera un archivo presentation.html, lo abrimos con el navegador y ya tenemos nuestra presentación.

Jun 01

Rails, Wicket, Grails, Play, Lift, JSP comparative -

(Source: javahispano.org)

May 30

Eclipse Color Themes

Eclipse Color Themes era algo que siempre había querido: Temas de colores oscuros en Eclipse. Algo fácil de instalar, nada de estar importando preferencias completas. Este plugin para Eclipse viene por defecto con un par de temas que no están nada mal (Ahora mismo estoy utilizando Obsidian) y también puedes crearte tu propio tema desde su página web

May 22

Log4Play: Log4j Appender and UI with Play Framework, Knockout.js and WebSockets -

playframework:

Log4Play is a Play! Framework module that provides a log4j appender which publishes log entries to an EventStream. Log4Play provides an user interface which uses a WebSocket to create a live stream of log messages. The user interface allows you to tail the logs of your application without needing to login to the actual box.

(via playframework)