Posts Tagged ‘java’

Deploying Play Framework 2 apps, with Java AND Scala, to Openshift

Let’s Play! in the cloud

A couple of weeks, Mark Atwood, Jorge Aliss, and me, Sebastián Scarano participated in Red Hat’s webinar LET’S PLAY! IN THE CLOUD: DEVELOPING JAVA WEB APPS ON OPENSHIFT

In the webinar Mark gave a neat introduction to Openshift, Red Hat’s free Platform as a Service:

Then we developed a basic contact manager web application, combining Java and Scala source code in the same Play 2 application, and deployed it on Openshift.

With this quickstart (https://github.com/opensas/play2-openshift-quickstart) you’ll be able to take any Play 2 application and deploy it on openshift. Just follow this instructions.

And here (https://github.com/opensas/play2-contacts-demo) you will find the contact demo app.

In the demo, in spite our internet connection conspiring against us, we managed to cover the following topics:

You can also check this article in which we explain in detail how we took advantage of the new “do-it-yourself” application type on Openshift to achieve native support for Play Framework application on Openshift.

So, if you want to start deploying your play apps on openshift right away, just sign up at openshift.com and enter PLAY!WEBINAR as promotional code, and you’ll get 3 gears, each with 1GB ram and 512 MB data space, for free.

Have fun playing on the cloud!

Advertisements

Play Framework posted values revisited

This is a follow up of palamago’s original tip: how to get a single POST value?

Working with posted values with Play Framework 2.0, without defining a form mapping, might not be so obvious as it was with Play 1.x, that’s why I’m writing this quick cheatsheet.

For this quick sample, let’s define the following view:

app/views/index.scala.html

@(message: String)

message: @message <br />

<h2>Scala form</h2>

<form action="@routes.ScalaPoster.save()" method="POST">
  scala name: <input name="scala_name"> <br />
  scala surname: <input name="scala_surname"> <br />
  <input type="submit" value="save">
</form>

<h2>Java form</h2>

<form action="@routes.JavaPoster.save()" method="POST">
  java name: <input name="java_name"> <br />
  java surname: <input name="java_surname"> <br />
  <input type="submit" value="save">
</form>

And the following routes file:

conf/routes

# Home page
GET     /                         controllers.Application.index

POST    /scala                    controllers.ScalaPoster.save
POST    /java                     controllers.JavaPoster.save

With java, accesing directly the request body:

app/controllers/JavaPoster.java

package controllers;

import play.mvc.*;

import views.html.*;

import java.util.Map;

public class JavaPoster extends Controller {
  
  public static Result save() {

    final Map<String, String[]> values = request().body().asFormUrlEncoded();
    final String name = values.get("java_name")[0];
    final String surname = values.get("java_surname")[0];
    
    return ok(index.render(String.format("You are %s, %s",surname, name)));
  }
  
}

Or using a DynamicForm:

package controllers;

import play.mvc.*;

import views.html.*;

import play.data.DynamicForm;

public class JavaPoster extends Controller {
  
  public static Result save() {

    final DynamicForm form = form().bindFromRequest();
    final String name = form.get("java_name");
    final String surname = form.get("java_surname");
    return ok(index.render(String.format("You are %s, %s",surname, name)));
  }
  
}

Now the scala version, accessing the body:

app/controllers/ScalaPoster.java

package controllers

import play.api.mvc._

object ScalaPoster extends Controller {

  def save = Action { request =>

    def name = request.body.asFormUrlEncoded.get("scala_name")(0)
    def surname = request.body.asFormUrlEncoded.get("scala_surname")(0)

    Ok(views.html.index("You are %s, %s".format(surname, name))) 
  }

}

And defining a form

package controllers

import play.api.mvc._

import play.api.data.Form
import play.api.data.Forms.tuple
import play.api.data.Forms.text

object ScalaPoster extends Controller {

  val form = Form(
    tuple(
      "scala_name" -> text,
      "scala_surname" -> text
    )
  )

  def save = Action { implicit request =>
 
    def values = form.bindFromRequest.data
    def name = values("scala_name")
    def surname = values("scala_surname")

    Ok(views.html.index("You are %s, %s".format(surname, name))) 
  }

}

Notice the implict request in the above sample. You could explicitly pass it to bindFromRequest with

    def values = form.bindFromRequest()(request).data

You can also play with the tuples and issue something like

    val data = form.bindFromRequest.get
    Ok(views.html.index("You are %s, %s".format(data._2, data._1))) 

or

    val (name, surname) = form.bindFromRequest.get
    Ok(views.html.index("You are %s, %s".format(surname, name))) 

And of course, if you just want to read a single posted value you could issue:

    def name = Form("scala_name" -> text).bindFromRequest.get

There are several ways to achieve it. I hope this serves as a useful reminder.

Desplegando aplicaciones de Play Framework 2, con Java Y Scala, en Openshift

Play framework en la nube de Red Hat

Hace un par de semanas, Mark Atwood, Jorge Aliss, y quien les escribe, Sebastián Scarano participamos del webinar LET’S PLAY! IN THE CLOUD: DEVELOPING JAVA WEB APPS ON OPENSHIFT organizado por Red Hat.

En el webinar, Mark dio una completa introducción a Openshift, la plataforma de cloud computing de Red Hat:

Luego junto con Jorge desarrollamos una simple agenda de contactos, usando Play Framework 2.0, combinando en una misma aplicación código fuente en Java y en Scala, y luego la pusimos en producción en Openshift.

Con este quickstart (https://github.com/opensas/play2-openshift-quickstart) podrán desplegar cualquier aplicación de Play 2.0 en Openshift. Simplemente sigan estas instrucciones.

Y aquí (https://github.com/opensas/play2-contacts-demo) encontrarán el código fuente de la agenda de contactos.

En la demo, a pesar de que nuestra conexión a internet nos jugó una mala pasada, logramos abordar los siguientes temas:

También pueden consultar este artículo en el cual analizamos en detalle cómo aprovechar el nuevo tipo de aplicación “do-it-yourself” (hagalo usted mismo) de Openshift para brindar soporte nativo a las aplicaciones de Play.

Si que si desean empezar a jugar con Openshift ya mismo, regístrense en openshift.com ingresen PLAY!WEBINAR como código de promoción, y recibirán 3 gears, cada uno con 1GB de memoria ram y 512 MB de espacio de almacemiento, gratis.

¡Esperamos que les guste!

Primer Hackaton de Play! framework para Scala y Java en Argentina



Anotate en el primer Hackaton de Play! Framework en Argentina.

  • ¿Cuándo? Sábado 5 de Mayo, a las 9:30 am
  • ¿Dónde? Costa Rica 5546, Buenos Aires, Argentina

Nuestro objetivo en este primer meetup es que todos podamos conocer juntos Play! Framework 2.0, cada uno probando lo que mas le interesa de este framework, en el lenguaje que desea.

La idea es que cada uno que se anote, elija 2 de los 5 tópicos que le interesaría aprender, junto con un nivel de expertise en Play 2.0 y un lenguaje en el cual quiera realizar la experiencia. En base a esto, se crearán parejas para poder realizar Pair Programming durante todo el hackaton.

La dinámica del Hackaton será la siguiente:

  1. Registración
    1. La registración comenzará a las 09:30 AM y continuará hasta las 10. Mientras nos vamos registrando vamos a poder desayunar café con medialunas
  2. Charla inicial de Play! Framework
    1. Se dará una charla inicial de 30 a 45 minutos de Play! Framework 2.0 con ejemplos tanto en Scala como Java. Esta introducción nos permitirá tener a todos una idea básica de que es Play!
  3. División de proyectos
    1. En base a las personas que estamos en el Hackaton y a los resultados de la encuesta, se crearán diversos proyectos pequeños que abarquen estas ideas. Se separarán a todas las personas en estos proyectos de a pares, para poder realizar Pair Programming
  4. Trabajo en los equipos asignados hasta las 1730
  5. Almuerzo
    1. El almuerzo estará incluido. Se proveerán Pizzas con bebidas para que todos podamos comer mientras codeamos.
  6. Conclusiones
    1. Cada grupo debera preparar una mini charla de aproximadamente 10 minutos donde contarán los problemas y soluciones que se encontraron, mostrando un poco del código que hicieron

Para poder participar, es importante que traigas tu notebook y cuentes con:

  • Cuenta en GitHub
  • Conocimientos de Git
  • Conocimientos de Java y/o Scala

Aquí tienen información que pueden ir leyendo para ir informándose del tema:

Los esperamos 😀

First Play! framework hackaton for Scala and Java in Argentina



Reserve your place at thefirst Play! framework Hackaton in Argentina.

  • ¿When? Saturday, May 5, 2012, 9:30 AM
  • ¿Where? Costa Rica 5546, Buenos Aires, Argentina

Our goal in this first meetup is to get to know Play! 2.0, focusing on what is more interesting for each of us, in the language we prefer.

Here you have the complete announcement in spanish.

Some useful resources:

Playframework + Google Guice (Español)

Note: This article is also available in english.

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

Cómo usar el módulo

Añadir la dependencia:

require:
  - play
  - play -> guice 1.2

Descargar las dependencias

play deps

Crear una nueva clase que será la que se inyectará en el controlador.

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");
    }
}

Configurar el inyector de dependencias

package config;
public class GuiceConfig extends GuiceSupport {
    @Override
    protected Injector configure() {
        return Guice.createInjector(new AbstractModule() {
            @Override
            protected void configure() {
                bind(MyService.class).to(MyServiceImpl.class).in(Singleton.class);
            }
        });
    }
}

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.

Para inyectar la clase se utiliza la anotación @Inject

package controllers;
public class Application extends Controller {

    @Inject
    static MyService myService;

    public static void index() {
        myService.sayHello();
        render();
    }
}

Testing

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);
    }
}

Añadiendo más dependencias

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.MyDependentService

package services;

public interface MyDependentService {
    public void sayHelloWorld();
}

service.MyDependentServiceImpl

package services;

@InjectSupport
public class MyDependentServiceImpl implements MyDependentService {

    @Inject
    static MyService myService;

    public MyDependentServiceImpl(){
        play.Logger.info("Init 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();
}

}

Binding en GuiceConfig

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

Y esta es la salida por la consola

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

Inyección por parámetro del constructor

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");
    }

    ...

Lazy Singletons

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 ~ Init MyServiceImpl
22:00:04,824 INFO ~ Init MyDependentServiceImpl
22:00:04,824 INFO ~ Application 'lazySingleton' is now started !

Oops! 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 - before getInstance");
        MyService instance = injector.getInstance(MyService.class);
        System.out.println("development - after getInstance");
    }

    @Test
    public void testProduction(){
        Injector injector = createInjector(Stage.PRODUCTION);
        System.out.println("production - before getInstance");
        MyService instance = injector.getInstance(MyService.class);
        System.out.println("production - after 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 - before getInstance
INFO: Inicializando MyServiceImpl
INFO: development - after getInstance

INFO: Inicializando MyServiceImpl
INFO: production - before getInstance
INFO: production - after 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

Este es el código:

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 próxy 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.

Conclusión

Durante los últimos años la inyección de dependencia ha evolucionado convirtiéndose en un recurso que utilizan a diario los programadores. En este artículos hemos visto lo sencillo que es integrar Guice en una aplicación que utiliza play framework. También hemos visto cómo configurar la librería para conseguir una mejor experiencia durante el desarrollo.

Artículo original publicado en http://axelhzf.tumblr.com.

%d bloggers like this: