Archive for the ‘Playframework’ Category

Play! Framework 2 (2.1) Scala with Slick made easy (With example)

by @mgonto, original article can be found here

Hi everyone!

First of all, I want to tell you that the original post is from here (Blogeek).

Today I’ve seen some videos about Slick and Play! Framework 2.1 and I got excited, so I thought, let’s code an app with Slick. What did I realize? It wasn’t that simple. Play! isn’t yet thought to work with Slick very well.

First of all, if you want to see this example complete you can go to

https://github.com/mgonto/slick-play2-example

In Slick, you create table definitions for the class you want to use. However, all of the imports for the Table, the columns, etc. are driver dependant. So, when you change the driver, you don’t want to change the import in the code. You just want to change a configuration in the application.conf from Play! Framework. That’s exactly what I did.

So, let’s see first how it’s implemented. Every Driver (H2, Postgres, etc) extends from a trait called ExtendedProfile. So, I needed my table classes to use some profile that was injected by me. Once I realized that I needed to make some DI I thought about Cake Pattern. For more information about the Cake Pattern please viisit Cake pattern

So, the first thing I implemented was a Trait Profile with an abstract Extended Profile value:

package models

import slick.driver.ExtendedProfile

trait Profile {
  val profile: ExtendedProfile
}

After this, I needed to create the Users table. That Users table needed the profile, so I’d create a UserModule which would need the Profile trait. Then, as I’d mix with a Profile trait, I’d import the things from the abstract ExtendedProfile field and everything would compile. Then I create the users table with an ID and a Name (pretty simple)

package models

case class User(id: Option[Int], name : String)

trait UserComponent {
  this: Profile =>

  import profile.simple._

  object Users extends Table[User]("users") {
    def id = column[Int]("id", O.PrimaryKey)
    def name =  column[String]("name", O.NotNull)
    def * = id.? ~ name <> (User, User.unapply _)

    def add(user: User)(implicit session: Session) = {
      this.insert(user)
    }

    def countByName(name: String)(implicit session: Session) = {
      (for {
        user <- Users
        if (user.name === name)
      } yield(user)).list.size
    }

  }
}

After this, I create a DataAccessLayer class (DAL) which would receive the ExtendedProfile as a constructor parameter and then would include the other traits (Profile and UserModule)

package models

import slick.driver.ExtendedProfile

class DAL(override val profile: ExtendedProfile) extends UserComponent with Profile {

  import profile.simple._

  def create(implicit session: Session): Unit = {
    Users.ddl.create //helper method to create all tables
  }
}

After this, I have everything to create a DAL from a given profile. However, now I needed a way to configure the profile, so I added a new property in the application.conf.

slick.db.driver=scala.slick.driver.H2Driver

Then, I created a trait that would import this driver from the conf and create the database to do the queries and the dal with the corresponding profile. It has two methods, getDb and getDal which will be then used by two other classes.

package models

import slick.session.Database
import play.api.db.DB
import play.api.Application
import slick.driver.ExtendedProfile

trait DBeable {

  val SLICK_DRIVER = "slick.db.driver"
  val DEFAULT_SLICK_DRIVER = "scala.slick.driver.H2Driver"

  def getDal(implicit app : Application) : DAL = {
    val driverClass = app.configuration.getString(SLICK_DRIVER).getOrElse(DEFAULT_SLICK_DRIVER)
    val driver = singleton[ExtendedProfile](driverClass)
    new DAL(driver)
  }

  def getDb(implicit app : Application) = {
    Database.forDataSource(DB.getDataSource())
  }

  private def singleton[T](name : String)(implicit man: Manifest[T]) : T =
    Class.forName(name + "$").getField("MODULE$").get(man.runtimeClass).asInstanceOf[T]

}

The only things left are creating the DB once the app starts and having a singleton object to be able to ask for the dal and the database to do the queries from a controller. This is done as following:

import models.{User, DBeable, AppDB}
import play.api.db.DB
import play.api.GlobalSettings
import play.api.Application
import slick.session.Session

object Global extends GlobalSettings with DBeable {

  override def onStart(app: Application) {
    implicit val application = app
    lazy val database = getDb
    lazy val dal = getDal
    database.withSession {
      implicit session: Session =>
        dal.create
    }
  }
}
package models
import play.api.Play.current
object AppDB extends DBeable {

  lazy val database = getDb
  lazy val dal = getDal

}

And that’s it :). Now you have everything configured to start coding. I’ve tried if everything was working with a test as following.

class UserSpec extends Specification {

  "User" should {

    "be saved" in {
      running(FakeApplication(additionalConfiguration = inMemoryDatabase())) {
        AppDB.database.withSession {
          implicit session: Session =>
            AppDB.dal.Users.add(User(Some(2), "hola"))
            AppDB.dal.Users.countByName("pepe") must beEqualTo(0)
            AppDB.dal.Users.countByName("hola") must beEqualTo(1)

        }
      }
    }
  }
}

And that’s it 🙂 Now you have Play! configured for running with Slick.

Cya people!

Soporte nativo para Play framework en Openshift con el nuevo tipo de aplicación DIY

Por Sebastián Scarano @develsas. La versión original de este artículo está disponible en el Blog oficial de Openshift

Ya está en línea el contenido del webinar en el que mostramos cómo desarrollar una aplicación de Play 2.0, combinando Java Y Scala en la misma aplicación, y ponerla en producción en Openshift.

Cuando todas las opciones no son suficientes

Hace tan sólo algunos días nos enteremos del lanzamiento de un nuevo tipo de aplicación en Openshift denominada “do-it-yourself” o “hágalo-usted-mismo”. En este artículo mostraremos cómo podemos sacar el máximo provecho de esta nueva herramienta que se suma al arsenal de Openshift.

¿Qué es Play? Play es un framework que nos permite desarrollador aplicaciones Web, con Java o Scala, de una manera mucho más fácil, permitiéndonos alcanzar niveles de productividad que hasta el momento parecían patrimonio exclusivo de los frameworks basados en lenguajes dinámicos, como rails o django. Play forma parte también de los nuevos frameworks que se atrevieron a darle la espalda a la API de servlets y decidieron tomar otro rumbo. Es así como Play implementa su propio servidor http, sumamente liviano y optimizado, preparado para funcionar de manera asincrónica. Todo esto haciendo uso de Netty, una librería específicamente pensada para desarrollar este tipo de servidores, y que casualmente forma parte del stack de Jboss.

Ahora bien, si ya conoce Openshift, sabrá que le brinda múltiples opciones a la hora de desarrollar y poner en producción sus aplicaciones en la nube de Red Hat. Puede elegir trabajar con PHP, Ruby, Perl, Python, Node.js o Java. Y en lo que respecta a la base de datos puede elegir entre MySQL, PostreSQL y MongoDB.

Sin embargo, a pesar de esta abundante cantidad de opciones, el desarrollo de aplicaciones web se mueve a un ritmo tan rápido que ninguna plataforma es capaz de seguirle el paso. Cada día es más común trabajar con servidores http hechos a medida, construidos pensando en alta escalabilidad con bajo consumo de recursos. En lo que respecta a Java, el omnipresente servlet container, ya ha dejado de ser la única opción disponible.

Frente a este panorama, ¿qué podemos hacer para soportar todas estas heterogéneas tecnologías en constante movimiento? Bueno, los ingenieros de Red Hat dieron con una solución muy simple, pero al mismo tiempo sumamente poderosa.

Presentando el tipo de aplicación DIY – Hágalo-usted-mismo

Estos son los tipos de aplicación actualmente soportados en Openshift: jbossas-7, python-2.6, jenkins-1.4, ruby-1.8, diy-0.1, php-5.3, and perl-5.10

Bueno, no cuesta mucho darse cuenta de qué trata cada uno, salvo uno de ellos que se ve un tanto sospechoso: diy-0.1

Una aplicación “DIY” no es más que una aplicación completamente vacía, sin ningún framework ni servidor previamente cargado, listo para que lo personalicemos según nuestras propias necesidades. Con este nuevo tipo de aplicación, Openshift está comenzado a hacer más difusa la línea que separa un IaaS (Infraestructura como servicio) de un PaaS (Plataforma como servicio), poniendo a nuestro alcance un entorno controlado y escalable, pero al mismo tiempo dándonos la libertad para implementar la tecnología que mejor se ajuste a nuestras necesidades. [Tenga en cuenta que al momento de escribir este artículo, el tipo de aplicación DIY se encuentra en estado experimental]

Soporte nativo de Play en Openshift

Para mostrar las posibilidades que este nuevo tipo de aplicación pone en nuestras manos, implementaremos uno de los pedidos más votados en Openshift: soporte nativo para Play framework.

Hasta el día de hoy, para poner en producción una aplicación Play en Openshift, la única opción que teníamos era empaquetarla en un archivo war y desplegarla en un servlet container, lo cual funcionaba muy bien y era muy fácil, como explica este artículo. La única contra era que al hacerlo desperciábamos preciosos recursos y no podíamos hacer uso de prestaciones avanzadas de Play, como el manejo de requests asincrónicos.

Para darse una idea de qué es lo que nos proponemos conseguir, pueden echar una mirada al quickstart que preparamos para este artículo. Simplemente tienen que crear una nueva aplicación en Openshift, eligiendo como tipo diy-0.1, hacer un pull de los fuentes del quickstart, y luego hacer un push a su repositorio de openshift… ¡y eso es todo! Aquí están los pasos:

rhc app create -a play -t diy-0.1 -l yourlogin@yourmail.com
cd play 
git remote add quickstart -m master https://github.com/opensas/play-example.git
git pull -s recursive -X theirs quickstart master 
git push 

Luego de completados esos pasos, su aplicación estará lista y esperándolo en http://play-yournamespace.rhcloud.com

También hemos preparado un quickstart para Play framework 2.

Ahora, si tiene ganas de meterse a fondo y ver cómo hemos logrado esto, y al mismo tiempo prepararse para empezar a crear sus propios quickstarts, no tiene más que seguir leyendo…

¡Adiós a los servlets!

Antes de intentar crear una aplicación de tipo DIY en Openshift, tendrá que familizarse con la tecnología que planea poner en producción. Es preciso conocer en detalle los pasos necesarios para configurar todas las herramientas necesarias en su propia estación de trabajo, para luego replicar esto en Openshift.

En el caso de una aplicación de Play framework, no necesitaremos un completo servidor de aplicaciones como Jboss, ni tampoco un servidor web al estilo Tomcat, es más, ni siquiera un simple servlet container. Tan sólo tendremos que instalar Play e iniciar el servidor http que trae incluido.

Hacer esto en su propia estación de trabajo es tan fácil como descargar Play de la web, descomprimirlo y ejecutar:

play new demo 
cd demo 
play start

Y para detener la aplicación:

play stop

Ahora tan solo tendremos que hacer esto mismo en nuestro servidor en Openshift.

Conociendo nuestra propia nube

Vamos a crear una nueva aplicación en Openshift, de tipo diy-1.0, llamada ‘raw’.

rhc app create -a raw -t diy-0.1 -l yourlogin@yourmail.com

Ahora echémosle una mirada a lo que acabamos de crear

rhc app show -a raw -l yourlogin@yourmail.com

Application Info
================
raw
    Framework: diy-0.1
     Creation: 2012-03-19T01:18:31-04:00
         UUID: youruuid
      Git URL: ssh://youruuid@raw-yourdomain.rhcloud.com/~/git/raw.git/
   Public URL: http://raw-yourdomain.rhcloud.com/

Puede navegar a http://raw-yourdomain.rhcloud.com/ para ver la página de nuestro sitio.

Es la misma página estática que encontraremos en raw/index.html

Ahora veamos que nos espera en nuestro repositorio local:

cd raw
ls -a

.git                      # nuestro repositorio local de git
misc                      # un directorio vacío, puede borrarlo, nadie extrañará su presencia
.openshift/action_hooks   # aquí están los scripts para iniciar y frenar nuestra aplicación
raw                       # la paǵina estática de error
README                    # información de utilidad

Como ya dijimos, una aplicación completamente vacía, pero hay una carpeta que nos resultará particularmente interesante:

ls .openshift/actions_hooks
build  deploy  post_deploy  pre_build  start  stop

Estos son los scripts que Openshift utiliza para compilar, desplegar, iniciar y detener nuestra aplicación. Estos escripts son ejecutados en el servidor remoto de Openshift luego de cada push. Así que ahora los analizaremos en detalle para conocer mejor el entorno en que correrá nuestra aplicación.

Tomemos la salida del comando `rhc app show -a raw` y ejecutemos el siguiente comando:

ssh youruuid@raw-yourdomain.rhcloud.com

De esta manera podrá acceder a su máquina remota en openshift. En su directorio HOME encontrará los siguientes directorios:

git
    .env            # Contiene la definición de las variables de entorno

    .git  # Aquí está su propio repositorio de git, disponible en ssh://youruuid@raw-yourdomain.rhcloud.com/~/git/raw.git/



    repo            # $OPENSHIFT_DATA_DIR - Aquí está el contenido de la carpeta de su aplicación.
                    # Cada vez que hace un push, los datos se guardan aquí.

    data            # $OPENSHIFT_DATA_DIR - Este es un directorio persistente, 
                    # la info que guarde allí no se irá con cada reinicio del servidor

    logs            # $OPENSHIFT_LOG_DIR - Aquí debería guardar los archivos de log de su aplicación
                    # Es la carpeta que consulta el comando 'rhc app tail'

/tmp/             # $OPENSHIFT_TMP_DIR - Carpeta temporal, aquí tenemos permiso de lectura y escritura

Estas son básicamente las carpetas que más nos interesan.

Basta de discursos, queremos ver el código

Para este artículo tomaremos una versión simplificada del quickstart para desplegar aplicaciones Play 1.x en Openshift. Agregamos links a los scripts originales para que pueda consultarlos.

Antes que nada tendremos que desarrollar el script .openshift/action_hooks/pre_build, que será el encargado de verificar que el framework se encuentre instalado. De no ser así, deberá descargarlo de la web y descomprimirlo.

El script podría ser algo tan simple como esto:

.openshift/action_hooks/pre_build (script en github)

if ! [[ -d ${OPENSHIFT_DATA_DIR}play-1.2.4 ]]; then
  curl -o ${OPENSHIFT_DATA_DIR}play-1.2.4.zip http://download.playframework.org/releases/play-1.2.4.zip
  unzip ${OPENSHIFT_DATA_DIR}play-1.2.4.zip
  rm ${OPENSHIFT_DATA_DIR}play-1.2.4.zip
fi

Luego, para iniciar la aplicación:

.openshift/action_hooks/start (script en github)

cd ${OPENSHIFT_REPO_DIR}

.openshift/action_hooks/stop

#le indicamos a Play que guarde los archivos de auditoria en el directorio OPENSHIFT_LOG_DIR
export PLAY_LOG_PATH=${OPENSHIFT_LOG_DIR}

#ejecutamos la aplicación con el id openshift
${OPENSHIFT_DATA_DIR}play-1.2.4/play start --%openshift

No olvide configurar el su aplicación para que el servidor http escuche en el puerto ${OPENSHIFT_INTERNAL_PORT} de la dirección ${OPENSHIFT_INTERNAL_IP}

En nuestro caso simplemente deberemos agregar estas líneas al archivo application.conf:

%openshift.http.port=${OPENSHIFT_INTERNAL_PORT}
%openshift.http.address=${OPENSHIFT_INTERNAL_IP}

Y ahora solo nos queda el script para detener la aplicación

.openshift/action_hooks/stop (script en github)

cd ${OPENSHIFT_REPO_DIR}

if [[ -f “server.pid” ]]; then
${OPENSHIFT_DATA_DIR}play-1.2.4/play stop
fi

¡Eso es todo!

Simplemente nos resta guardar los cambios en nuestro repositorio git y hacer un push a openshift:

git add .
git commit -m "nuestra aplicación de Play corriendo en Openshift"
git push

Entonces verá a nuestra criatura en acción, descargando e instalando play 1.2.4 del sitio de Play, y finalmente ejecutando nuestra aplicación. No sea tímido, hágale una visita en : http://raw-yourdomain.rhcloud.com/

Recuerde que esta es una versión simplificada del quickstart original, no estamos chequeando errores ni guardando información en el archivo de logs. Para un ejemplo más completo consulte los scripts del quickstart en Openshift.

Play y Openshift, jugando en la nube de Red Hat

Desde sus inicios Openshift se destacó por brindar soporte a una amplísima gama de frameworks y servidores web. Con esta nueva opción, también nos brinda las herramientas necesarias para personalizarlo según nuestras necesidades. Lo único que necesita es familiarizarse con el entorno de Openshift y comenzar a programar unos simples scripts en bash. Me pregunto qué creará la comunidad con este nuevo tipo de aplicación Do-It-Yourself en Openshift.

Por Sebastián Scarano @develsas

Sebastián Scarano es un desarrollador web de Buenos Aires, apasionado por compartir su conocimiento y desarrollar buenos sitios web. Actualmente se desempeña como líder de proyectos en el Ministerio de Trabajo, Empleo y Seguridad Social de la República Argentina. Durante el último año ha estado participando activamente de la comunidad Play. Más recientemente publicó el módulo Openshift para Play, para que todos puedan desplegar fácilmente sus aplicaciones en la nube de Red Hat.

Exponiendo y consumiendo servicios de datos con mybatis, play framework 2.0 y jersey

Tomado del blog gishak.wordpress.com

 

Voy a escribir en esta ocasión sobre como exponer servicios de datos con play 2.0, utilizando mybatis como mapeador de datos y la librería Jersey para consumir los servicios expuestos.

El modelo de datos con el que vamos a trabajar es el siguiente:

Como ven en el modelo no hago uso de claves foráneas, ni PK compuestas, eso es una práctica (buena o mala) personal, así que no se alarmen si no ven un modelo ER típico.

Empezando con mybatis (anteriormente ibatis); es un mapeador de datos muy simple de utilizar y muy flexible; he sido fan de hibernate desde sus primeras versiones pero me he encontrado con la simplicidad de este framework que no te quita el control del SQL que escribes (algo que para algunos desarrolladores es importante), pero a su vez hace realmente fácil el mapeo entre las tablas y los objetos.

Hay varias opciones para el mapeo de datos con mybatis, en mi caso me gusta tener la conexión a la base de datos en XML y los mapeos con anotaciones (también se pueden hacer con XML al estilo de los .hbml), así que lo primero es crear un archivo de configuración, en este caso lo llamamos dbconfig.xml.

Ahora En el archivo de configuración dbconfig.xml, como estoy utilizando jdbc de SQL Server la configuración va de la siguiente manera

<pre><configuration>
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
				<property name="url" value="jdbc:sqlserver://localhost\sql2008:51085;databaseName=dummy" />
				<property name="username" value="user" />
				<property name="password" value="secret" />
			</dataSource>
		</environment>
	</environments>
</configuration>

Tomando como ejemplo del modelo una de las clases:

public class Genre implements Serializable{

	private static final long serialVersionUID = -9130550406579029310L;
	private int id;
	private String name;

	public Genre(){
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return String.format("%s - %s", this.id, this.name);
	}

}

Debemos definir una interfaz, la cual tiene las sentencias SQL y los métodos con las anotaciones correspondientes para el mapeo de los datos entre los objetos y la base de datos, los mapeos son para cualquier operación (Select, Update, Delete); para nuestro ejemplo vamos solo a hacer uso de Selects; de la clase Genre vamos a definir 2 métodos: Uno para consultar todos los registros de la base y otro para hacer una consulta por ID

public interface IGenreMapper {
	final String SELECT = "select id,name from genre";
	final String SELECT_BY_ID = "select id,name from genre where id=#{id}";

	@Select(SELECT)
	@Results(value = {
			@Result(column = "id", property = "id", javaType = Integer.class),
			@Result(column = "name", property = "name", javaType= String.class) })
	public List selectAll();

	@Select(SELECT_BY_ID)
	@Results(value = {
			@Result(column = "id", property = "id", javaType = Integer.class),
			@Result(column = "name", property = "name", javaType= String.class) })
	public Genre selectByID(@Param("id") int id);
}

Como se puede ver sobre los métodos está definida la anotación @Select que hace uso de las sentencias SQL que tenemos como Strings, y que de esas columnas seleccionadas tenemos el mapeo hacia que propiedades de la clase Genre corresponde cada una; y cuando estamos introduciendo parámetros #{nombre_párametro} en el comando sql como el caso del SELECT_BY_ID los podemos relacionar fácilmente con la anotación @Param con los párametros que se reciben en el método.

Una vez creada la interfaz hay que crear la clase que la implemente ya que ese es el objeto que finalmente se va a instanciar para hacer las consultas; la implementación es poca cosa, es simplemente invocar a una sesión de mybatis que nos devuelve un mapeador para que  internamente haga uso de lo definido en la interfaz de mapeo y obtener los resultados de la ejecución.

public class GenreDAO extends BaseDAO implements IGenreMapper{

public GenreDAO(SqlSession session){
		super(session);
	}

	@Override
	public List selectAll() {
		List result = session.getMapper(IGenreMapper.class).selectAll();
		closeSession();
		return result;
	}

	@Override
	public Genre selectByID(int id) {
		Genre result = session.getMapper(IGenreMapper.class).selectByID(id);
		closeSession();
		return result;
	}
}

Hay ciertos detalle en la clase mostrada, como por ejemplo heredar de un BaseDAO que tiene un constructor que recibe un objeto que implemente SqlSession de mybatis pero ya eso es como lo desees implementar, para mayor detalle pueden descargar el fuente relacionado al post en el link que se encuentra al final para que vean la implementación completa.

Algo que si voy a detallar es el caso cuando tenemos una propiedad compleja en nuestra clase; por ejemplo la clase Song tiene las propiedades Album y Genre que son del tipo de las clases Album y Genre respectivamente:

public class Song implements Serializable{

	private static final long serialVersionUID = -3728048783934199398L;
	private int id;
	private String name;
	private String duration;
	private Album album;
	private Genre genre;
        .
        .
        .
}

Así que para cargar las propiedades, en nuestra interface de mapeo utilizamos la anotación @One que nos permite llenar una propiedad compleja a partir de un método select que devuelva ese tipo de objeto. Como se mostro unas líneas arriba, el mapeador IGenreMapper tiene un método selectByID, del cual vamos a hacer uso en el mapeador Song para llenar la propiedad Genre, pasandole el id para que realice la consulta:

public interface ISongMapper {
	final String SELECT = "select id,album,name,duration,genre from song";

	@Select(SELECT)
	@Results( value= {
			@Result(column="id", property="id"),
			@Result(column="album", property="album", one=@One(select="com.musicservices.datamodel.mapper.IAlbumMapper.selectByID"),javaType=Album.class),
			@Result(column="name", property="name"),
			@Result(column="duration", property="duration"),
			@Result(column="genre", property="genre", one=@One(select="com.musicservices.datamodel.mapper.IGenreMapper.selectByID"), javaType=Genre.class)
	})
	public List selectAll();

}

La misma estrategia se sigue para cargar la propiedad Album, de esta manera el mapeo es completo desde nuestra base de datos relacional hacia el modelo de objetos aunque tengamos propiedades complejas.
Adicionalmente he creado una clase DataManager en la cual están las líneas donde se instancian los objetos de mybatis y el acceso a todos mis objetos DAO para centralizar el llamado a las clases, nos vamos a centrar en el código para instanciar el objeto SqlSessionFactory que es la interfaz entre nuestros objetos y la base de datos:

private DataManager(){
		if(sessionFactory == null){
			try {
				Reader reader = Resources.getResourceAsReader(DataManager.class.getClassLoader(),"dbconfig.xml");
				sessionFactory = new SqlSessionFactoryBuilder().build(reader);
				sessionFactory.getConfiguration().addMapper(IGenreMapper.class);
				sessionFactory.getConfiguration().addMapper(IAlbumMapper.class);
				sessionFactory.getConfiguration().addMapper(ISongMapper.class);
			} catch (IOException e) {
				e.printStackTrace();
			}

		}
	}

Aquí cargamos el archivo dbconfig.xml para poder crear la sesión de mybatis a través de la clase SessionFactoryBuilder, y luego de eso registramos todas las interfaces de mapeo que hayamos creado, las cuales le sirven a mybatis para hacer su trabajo, ya que como vimos en la implementación de las interfaces hacemos uso del metodo getMapper para hacer referencia a los mapeadores registrados.

Una vez con la capa de datos lista exportamos los binarios como un .jar y procedemos a exponerla como servicios Rest a traves del framework play, lo primero es descargar los binarios desde playframework.org descomprimirlo en un directorio (recomendado sin espacios en los nombres de las carpetas) y con el comando play new [NombreAplicacion] crear la estructura de un proyecto Java:

Para mayor comodidad y modificar los archivos creados por play podemos importarlo como un proyecto para Eclipse, para esto es recomendable agregar la ruta de instalación de play a las variables de ambiente para ubicarnos dentro del directorio de nuestra aplicación y ejecutar los comandos play y luego eclipsify, y luego de eso importamos el proyecto dentro de nuestro workspace de Eclipse (el paso es opcional ya que puedes editar los archivos desde cualquier editor de texto)


Navegando dentro de los directorios de nuestra aplicación play nos vamos a encontrar con las carpetas app y conf, que son las que vamos a utilizar para el ejemplo ya que solo vamos a hacer uso del framework para exponer servicios de datos, no vamos a abarcar toda la funcionalidad, solamente el enrutamiento por url hacia los controladores que van a hacer uso de nuestro modelo de datos para realizar las consultas a la base de datos.

Empezamos creando una carpeta lib en el proyecto de play y agregamos todas las dependencias de mybatis, jdbc, y el .jar creado con nuestro modelo de datos.

Ahora sí, lo primero es dentro de /app/controllers creamos un nuevo controlador Album.java que hereda de  play.mvc.controller y le agregamos un método estático public static Result all(), esta nueva notación es parte del nuevo play 2.0, en resumen vamos a crear un método que controle todos los requests realizados por HTTP GET a la ruta /album y los devuelva en formato Json, finalmente el código con todas las consideraciones antes mencionadas queda así:

public class Album extends Controller{

	@play.mvc.BodyParser.Of(Json.class)
	public static Result all(){
		ObjectMapper mapper = new ObjectMapper();
		String json = null;
		try {
			List<com.musicservices.datamodel.entities.Album> albumList = DataManager.Instance().albumDao().selectAll();
			json = mapper.writeValueAsString(albumList);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return ok(json);
	}
}

Una vez que tenemos el controlador debemos decirle a play cual es la url de la que este método del controlador se va a hacer responsable, modificamos el archivo /conf/routes y agregamos la línea para indicarle que todo lo que pase por /album y sea un HTTP GET va a ser manejado por nuestro controlador:

# Routes
# This file defines all application routes (Higher priority routes first)
# ~~~~

# Home page
GET     /                           controllers.Application.index()
GET	    /album                      controllers.Album.all()

# Map static resources from the /public folder to the /assets URL path
GET     /assets/*file               controllers.Assets.at(path="/public", file)

Listo, ahora procedemos a levantar nuestra aplicación en play con el comando run

*En dias previos a la redacción de este post aparecio la versión 2.0 de play y al tratar de referenciar al archivo xml de configuración de mybatis que se encuentra dentro del jar da un error de classpath, asi que como queria publicar el post como workaround deben copiar el archivo dbConfig.xml dentro de su aplicación play en la ruta [AplicacionPlay]\target\scala-2.9.1\classes 

Una vez que tenemos todo listo accedemos por URL a localhost:9000/album y vemos el resultado es un string con notación Json de la colección de resultados obtenidos:


Bajo el mismo esquema creamos el controlador para hacer consultas de Albumes por código, donde ahora el método debe recibir un parámetro, y llamamos al metodo selectByID del mapeador:

@play.mvc.BodyParser.Of(Json.class)
	public static Result getByID(Integer id){
		ObjectMapper mapper = new ObjectMapper();
		String json = null;
		try {
			com.musicservices.datamodel.entities.Album album = DataManager.Instance().albumDao().selectByID(id.intValue());
			json = mapper.writeValueAsString(album);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return ok(json);
	}

Y en la configuración de rutas debemos indicar el mapeo hacia el nuevo metodo controlador de la siguiente manera:

# Routes
# This file defines all application routes (Higher priority routes first)
# ~~~~

# Home page
GET     /                           controllers.Application.index()
GET	    /album                      controllers.Album.all()
GET	    /album/:id                 controllers.Album.getByID(id: Integer)

# Map static resources from the /public folder to the /assets URL path
GET     /assets/*file               controllers.Assets.at(path="/public", file)

Accedemos nuevamente por url a la ruta /album/{id} donde {id} en este caso es el valor de la columna id en la base de datos por la cual estamos consultando en al tabla Album, los resultados son los siguientes:

Y así podemos replicar el mismo esquema para todos los controladores que deseemos publicar. Ahora para consumir estos servicios Json vamos a hacer un simple cliente Java que haciendo uso de la libreria Jersey va a obtener via HTTP GET los resultados de la consulta y con la librería Gson de google vamos a regresarlos a su estado inicial de una Lista de objetos.

public static void main(String[] args) throws UnsupportedEncodingException{

		String albumName = URLEncoder.encode("Mane Attraction","UTF-8");
		String url = String.format("http://localhost:9000/song/album/%s",albumName);

		Client client = Client.create();
		WebResource res = client.resource(url);
		String jsonData = res.get(String.class);

		List<Song> songs = new ArrayList<>();
		Type listType = TypeToken.get(new TypeToken<Collection<Song>>(){}.getType()).getType();
		songs = new Gson().fromJson(jsonData, listType);
		for(Song s: songs){
			System.out.println(s);
		}
	}

En las primeras 2 líneas armamos la url al servicio expuesto de play, utilizando la clase URLEncoder ya que si no lo hacemos los espacios o cualquier caracter especial no se va a formatear correctamente, luego haciendo uso de las clases de Jersey generamos un WebResource de la url le hacemos un HTTP Get sólo con invocar el método del mismo nombre que nos devuelve el Json generado por nuestro servidor Rest; luego de esto tenemos que transformar este resultado en objetos manejables para java; por lo que hacemos uso de Gson, al cual tenemos que informarle el tipo de objeto al que debe transformar el String que le vamos a pasar, al pasar el tipo de la instancia de TypeToken<Collection<Song>> le indicamos que queremos transformar el Json a una lista de tipo Song, invocamos el metodo fromJson y listo estamos consumiendo ya los servicios expuestos de nuestro modelo de datos.
Los Rest services son una alternativa a los tradicionales Web Services, con play es tan simple como ya lo hemos visto; la flexibilidad de mybatis para mapear datos es fantastica y que podemos decir de las apis de Jersy y Gson que con no más de 9 líneas de código nos encapsulan una capa de comunicación y transformación de datos que debemos tener en cuenta y bajo nuestra amplia gama de frameworks para dar soluciones tecnológicas.

Saludos,

@gishac

 

Descargar fuentes

Play!1 …mas o menos completo (5)

Qué es lo siguiente?
Repasamos conceptos:
– Models (+JPA)

– Validaciones

Models (y JPA)

El Modelo es la última parte a entender en la arquitectura MVC.
Todas las clases model son guardadas en el directorio app/models.

Función

Como parte del modelo MVC es del núcleo de la aplicación. Éste contiene la representación de los datos de tu aplicación y la lógica de negocio para hacer las “funciones propias de una aplicación” (o algo así mal traducido, se entiende…). Como se escribió en posts anteriores, el propósito de la vista es renderizar el modelo y el propósito del controlador es actuar controlando la interface para correr acciones en el modelo de datos desde usuario.

Mientras que un framework no fuerza a que dejes de poner lógica de negocios en el controlador y usar el modelo como un objeto simple de acceso a los datos, los framework advierten que el Model es usado para ambas cosas, los datos y lógica de negocios. O sea: haga como quiera y va a funcionar, pero si desea trabajar correctamente haga como lo recomiendan los que saben.

Creando un Data Model (ó, Modelo de Datos)

Crear un Data Model es tremendamente fácil. Un data model en play es simplemente un set de clases de Java que son guardados en app/models. Pero hay algunas diferencias que necesita saber.
– las propiedades del modelo deben ser public (a eso agreguemos que no sea static ni final)
– No necesitas crear setters ni getters
Para los programadores Java con experiencia esto sonará raro y muy equivocado. No se preocupe, detrás de escena Play creará los setters y getters por usted. Play sugiere que con ello incrementa en algo la productividad. (se hablará más adelante)
Un ejemplo de un User puede ser:

package models;
 import play.libs.Codec;
 public class User {
 public String email;
 public String passwordHash;
 public String name;
 public boolean admin;
 public User(String email, String password, String name) {
 this.email = email;
 this.passwordHash = Codec.hexMD5(password);
 this.name = name;
 this.admin = false;
 }
 }

Sus futuras aplicaciones web fácilmente tendrán muchas clases que conformen el Modelo, pero para ser claros trabajaremos ejemplos con esas clases bien simples.

Persistencia en Bases de Datos usando JPA

Persistir en bases de datos con Play es una tarea extremadamente sencilla. Play hace uso de JPA (la API de Persistencia de Java) para guardar datos de tu modelo a la database en unas pocas líneas de código. De hecho, es de esperar que Play haga uso del estándar (y lo hace).
No hace falta preocuparse acerca del entity manager para guardar, borrar, actualizar o hacer consultas a la base de datos. Play abstrae todo eso por ti con algunos métodos disponibles en la clase model para tener tu aplicación corriendo inmediátamente.

Antes de seguir JPA en detalle, lo primero que debemos hacer es setear la base de datos, o algún lugar donde vayamos a guardar.

Seteando una Base de Datos
Play viene con un número de opciones que permiten dejar corriendo una base de datos de forma inmediata. Una vía rápida es usar una base de datos en memoria o incluso una base de datos basada en archivos. No es una solución permanente o una opción para un entorno productivo, pero permite empesar a usar una database sin tener instalado siquiera MySQL.
Por defecto,  una nueva aplicación de play no preconfigura la base de datos a usar, pero trae comentado un buen número de ejemplos.
El archivo de configuración es conf/application.cong. La parte que debemos ver es

 # Database configuration
 # ~~~~~
 # Enable a database engine if needed.
 # There are two built in values :
 #   - mem : for a transient in memory database (HSQL in memory)
 #   - fs  : for a simple file written database (HSQL file stored)
 #
 db=mem

La propiedad db es responsable de configurar la base de datos requerida. Aquí puedes ver que se usa la base de datos en memoria. HSQLDB (HyperSQL Java Database) es una base de datos open source que corre en memoria.
Es recomendable usar ésta porque es lo más rápido y fácil para empezar, y es prácticamente lo mismo que otra base de datos. Solo tienes que dejarlo descomentado (sin #).
Así mismo puedes ver que también figura MySQL o cualquier base con JDBC. Cestión de leer, descomentar y completar los campos (url, driver, user, pass).

Uso de JPA

Por debajo, Play usa Hibernate como implementación de JPA. Para convertir tu modelo en un modelo persistente necesitas agregar algunas líneas de código.
Volviendo a la clase User que se empezó en post anteriores, solo necesitamos hacer 2 cambios a la clase original para que tenga persistencia (incluir la anotación y extender de jpa)

package models;
 <span style="color: #008000;">@javax.persistence.Entity</span>
 public class User <span style="color: #008000;">extends play.db.jpa.Model</span>{
 public String email;
 public String passwordHash;
 public String name;
 public boolean admin;
 …
 }

Esas dos cosas:
– agregando la anotación @javax.persistence.Entity especificamos que la clase es una entidad JPA, y por eso ahora puede guardar datos.
– el segundo cambio hace que extienda de play.db.jpa.Model para hacer las cosas propias de CRUD.

Algunos de esos métodos se muestran aquí.

// find user
 User user = User.findById(1L);
 // update user email
 user.email = “notengo@email.com”;
 // update database
 user.save();
 …
 // delete user
 user.delete();
 …
 // find all users with certain criteria
 List<User> users = User.find(“admin = ?”, “true”).fetch();

Por ahora el objetivo solo es introducir este concepto.

Acceso directo a la base de datos

Nosotros deberíamos lograr hacer la mayoría de las cosas a través de JPA. Play accede através de la clase play.db.DB
Algunos de los métodos que se pueden usar para hacer consultas a la base de datos:

  • getConnection, te da acceso a el objeto Connection, desde el que creas tus consultas sql.
  • executeQuery, es un método que ejecuta un query en la conexión a la base de datos y retorna un objeto ResultSet.
  • execute, para ejecutar un update, retorna un booleano para informar si fue exitoso.

Play Cache

Cómo persistir datos? A los datos por lo general los guardamos de varias formas pero para mejorar la performance y tenerlos a mano podemos mantenerlos en caché.
Play tiene dos implementaciones de caché. Si está configurada en application.conf la memcached, Play usará ésta. Sinó usará la EhCache incluída para guardar el caché en el servidor.
Cuando escales la aplicación y deployes en múltiples servers, no puedes garantizar que los datos estén de request a request porque puedes pasar entre servidores. Pero esto es parte de la escencia de Play de la arquitectura ‘share nothing’.

Setters y Getters

Ya dijimos que con la clases Model los atributos van a ser privados y no habrá setters ni getters. La razón es acelerar el desarrollo. Seguro habrás notado que Play convierte las clases en tiempo de ejecusión volviendo los atributos a privado y crea setters y getters.
La razón principal para crear atributos privados y hacer setters y getters, es que esto fuerza mejores prácticas para encapsulación. Encapsulación es parte del núcleo de Java y programación Orientada a Objetos, y Play no saltea eso. Justamente reconoce eso que tan tedioso de crear setters y getters para los atributos privados, cuando el 95% del tiempo simplemente devuelve una variable sin tocar.
Si queremos crear setters y getters para los atributos (aunque debemos mantener los atributos como public) podemos hacerlo. En tiempo de ejecución, Play chequeará para ver si los setters y getters ya existen.

Validaciones

Función

En la mayor parte de las aplicaciones web vamos a necesitar tener cierto nuvel de validación en los parámetros que los controladores reciben como parte de un evento. Play tiene un número de opciones para hacer validaciones en las entradas del usuario y devuelve mensajes al navegador.

Uso Básico

La forma más fácil para entender como la validación ayuda a trabajar en una clase es a través de ejemplos.
Entonces un registro de usuario en el controlador podría ser así:

public static void register(String user, String email, String password) {
 // checkear que el usuario ha sido suministrado
 validation.required(user);
 // chekear que la dirección de email es válida
 validation.email(email);
 // checkear que el password tenga entre 6 y 10 caracteres
 validation.minSize(password, 6);
 validation.maxSize(password, 10);
 …
 render();
 }

No hace falta aclarar que hicimos en cada renglón…
Si cualquiera de las rutinas de validación falla, un error va a ser agregado a la lista de errores.

En fin, podrías acceder a la lista de errores en la validación del objeto directamente haciendo esto:

public static void register(String user, String email, String password) {
 // checkea si dieron el usuario
 if (user == null || user.length() == 0) {
 validation.addError(“user”, “Debe ingresar el nombre de usuario”);
 }
 …
 }

A veces que las validaciones se vuelven complejas, pero las validaciones ayudan a tus métodos tener soluciones mucho más limpias, fáciles de leer y asegurar consistencia a la aplicación de Play, haciendo todo más mantenible.

Mensajes por defecto

Por ahora en el ejemplo usamos los mensajes por defecto que provienen del archivo de mensajes (message).
Cuando usamos los metodos de validación, Play automáticamente crea un mensaje por defecto dependiendo del tipo de método de error usado.
Por ejemplo, si queremos hacer una validacion del parámetro de usuario, Play buscará el mensaje “validation.required” en el archivo de mensajes. Puedes crear algo así:

validation.required=Debe entrar el valor para %s

El %s va a reemplazarse por el nombre de la variable que falle la validación. Así, todos los métodos validation.required serán usados para el mismo mensaje de error de validación (claro que todo puede customizarse).

Custom Messages

Para poner un mensaje personalizado a una rutina de validación tenemos que agregarlo al método después de la llamada a la validación .message(“…”);

public static void register(String user, String email, String password) {

// checkear si ha sido dado el usuario
 validation.required(user).message(“Ingrese su nombre de usuario”);

// checkear si el email es válido
 validation.email(email).message(“El email es inválido”);

// checkear si el password tiene entre 6 & 10 caracteres
 validation.minSize(password, 6).message(
 “El password debe tener al menos 6 dígitos”);
 validation.maxSize(password, 10).message(
 “El password debe tener nomás de 10 dígitos”);
 … }

Los mensajes pueden ser texto plano o podrían ser una clave para acceder a un archivo de mensajes.

Mostrando mensajes en la Vista

La validación de parámetros no es suficiente para permitir saber al usaurio que está haciendo algo mal, hay que mostrar el error al usuario para que sea conciente algo no fue del todo bien.
Play provee algunos tags que ayudan a mostrar mensajes de error en la vista.

  • #{ifErrors}, que nos deja ver el error donde fue encontrado por el controlador. El #{else} podríamos usar para mostrar diferentes resultados dependiendo si había error o no. (suena confuso, pero a esta altura pero podríamos usar un poco la imaginación sobre qué podríamos hacer usando un else, algo obvio).
  • #{errors}, itera sobre la lista de errores para mostrarnos una lista sobre lo que encontró
  • #{error ‘fieldname’/}, permite especificar el mensaje de error para algo específico. Es útil si queremos mostrar un mensaje de error luego del elemento del formulario en donde se originó el error.

Ejemplo usando los tags:

#{ifErrors}
 <h1>Errores Encontrados</h1>
 <p>Pocesando su petición de registro encontramos errores. </p>
 <ul>
 #{errors}
 <li>${error}</li>
 #{/errors}
 </ul>
 <p>Please go back and check the details and try again</p>
 #{/ifErrors}
 #{else}
 The registration process was successful!
 #{/else}

Volver hacia el formulario de envío

En el ejemplo previo, el controlador renderiza la vista por defecto, que es la misma página y no tiene en cuenta si en donde aparecieron los errores o no. Necesitaríamos volver atrás hasta el formulario de donde vienen los errores.
Hay algunos pasos extra que necesitamos hacer para que esto funcione. Cuando redireccionamos, Play envía una solicitud devuelta al browser para decirle que cargue el URL redireccionado y asegure el estado siempre consistente con la URL solicitada. Por eso, cuando la página es renderizada los errores se van a perder porque empezamos una nueva acción, y el objeto de validación se creó por cada nueva acción, a menos que especifiquemos un request para mantener disponibles los errores mediante una request extra.
Para hacer esto necesitamos cambiar nuestro controlador y trabajar de la siguiente forma:

public static void register(String user, String email, String password){

//checkear que dieron el usuario
 validation.required(user);

//chekear que la dirección de mail es válida
 validation.email(email);

//checkear que el password del usuario esté entre 6 y 10 caracteres.
 validation.minSize(password, 6);
 validation.maxSize(password, 10);

//volver al formulario de registro si hay errores
 if(validation.hasErrors()) {
 params.flash();
 validation.keep();
 registrationForm();
 }
 // si no hay errores, mostrar la página que se ha completado con éxito
 render();
 }

Necesitaríamos cambiar nuestra página registrationForm para incluir los tags ifErrors y mostrar los mensajes como una lista o en cada ítem del formulario. Para mostrar cada item la página quedaría parecida a esto:

#{ifErrors}
 <h1>Se Encontraron Errores</h1>
 #{/ifErrors}

#{form @Application.register()}
 <div>
 Nombre: <input type=”text” name=”user” value=”${flash.user}” />
 <span class=”error”>#{error ‘user’ /}</span>
 </div>
 <div>
 Email:<input type=”type” name=”email” value=”${flash.age}” />
 <span class=”error”>#{error ‘email’ /></span>
 </div>
 <div>
 Password: <input type=”text” name=”password” value=”${flash.password}” />
 <span class=”error”>#{error ‘password’ /}</span>
 </div>
 <div> <input type=”submit” value=”Register” /> </div>
 #{/form}

Errores Anidados (Nesting Errors)

Esto puede corresponder a, si por ejemplo, queremos primero verificar la clave sólo si primero ingresó correctamente el nombre de usuario.
Para hacer esto podemos usar el atributo ok en el resultado de la validación.

if (validation.required(user).message(“Por favor ingrese el usuario”)<span style="color: #003366;">.ok</span>) {
 validation.minSize(user, 6).message(
 “El usuario debe tener al menos 6 caracteres.”);
 validation.maxSize(user, 20).message(
 “El usuario no debe superar los 20 caracteres.”);
 }

Usando Anotaciones

Mas que usar una clase que ayude a validar, Play ofrece otra vía para validar el contenido de datos que se pasan al controlador, usando anotaciones.
Para cada validación hay un método, una anotación equivalente. Así, para el ejemplo de registro podríamos hacerlo así:

public static void register(@Required String user, @Email String email,
 @MinSize(6) @MaxSize(10) String password) {
 // volver al formulario de registro si hay errores
 if(validation.hasErrors()) {
 params.flash();
 validation.keep();
 registrationForm();
 }
 // si no hay errores renderizar la página siguiente
 render();
 }

Objeto Anotaciones

Las anotaciones son muy prácticas para validación de parámetros individuales, podemos pasar objetos como parámetros en Play. Es posible agregar anotaciones de validación a la clase del modelo, y de pasar objetos como parámetros ahora usando anotaciones.
Para esto simplemente usamos la anotación @Valid para el objeto pasado como parámetro, indicando que queremos validar el objeto, a continuación uso las anotaciones de validación que vimos para validar por separado los atributos de el objeto model.
El controlador quedaría similar a esto:

public static void register(@Valid User user){
 …
 }

La clase model User quedaría así:

public class User {
 @Required
 public String user;
 @Email
 public String email;
 @MinSize(6)
 @MaxSize(10)
 public String password;
 …
 }

Validaciones Personalizadas

Podemos crear nuestra propia validación usando la anotación @CheckWith que usa una clase para validación.
Vemos un ejemplo que valide un password que exija incluir números y caracteres.

public class User {
 @Required
 @CheckWith(ChequeaLetrasPass.class)
 public String password;

static class ChequeaLetrasPass extends Check {
 public abstract boolean isSatisfied(Object user, Object password){
 return contieneLetrasYNumeros(password);
 }
 }
 }

La forma que esto trabaja es que el @CheckWith especifica una clase que presenta la rutina que vamos a usar. La clase debe extender de play.data.valitation.Check e implementar el método isSatisfied. Los objetos son: la clase que contiene el atributo que va a ser validado y el atributo mismo.
Simplemente devueve un booleano en true si la validación pasó, sinó un false.

@wfranck

Play!, Openshift y Twitter Bootstrap: Combo para programadores perezosos pero impacientes

Ya que estan, por que no se pegan una vuelta por el sitio de openshift y votan para agregar soporte nativo para Play en Openshift.

Hace rato que descubri en Play un poderosisimo web framework para Java, y tengo la suerte de poder aplicarlo diariamente en mi actual trabajo. Sin entrar en demasiados detalles tenemos todos los beneficios del conocido patron MVC, junto con un poderoso WebApp container y un sistema de templates muy amigable. Pero lo que lo hace mas amigable y poderoso a mi parecer es la comunidad y lo facil que resulta desarrollar e integrar los famosos modulos de Play. El que mas nos ocupa hoy es el de Openshift cuyo autor es Sebastian Scarano akka @opensas (el que “mas” lo digo porque el desarrollo incluye dos mas que son nativos: CRUD y Secure)

Disclaimer: Como entiendo que mi post es acotado y especifico quizas cometa el error de dar por sentado un monton de cosas, pero si necesitan que me extienda en algun punto por favor haganmelo saber.

Instalacion y armado del entorno

Deben contar con Git y !Play instalado. Si todavia no lo hicieron, vayan a al sitio de !Play. Y tambien

(sudo) apt-get install git-core

Tambien van a necesitar el cliente de Openshift. Para ello

(sudo) gem install rhc

y

(sudo) gem install test-unit

A continuacion en su directorio de trabajo ejecutan

(sudo) play install openshift

Con esto ya tenemos el modulo de Openshift instalado en nuestro stack de !Play. A continuacion creamos nuestra aplicacion de la siguiente manera:

play new myApp --with openshift

Acto seguido haran vuestra magia con la aplicacion, corriendola en modo local y versionadolo debidamente ;-). Pero atentos que deben trabajar con Git puntualmente ya que OpenShift les creara un repo propio a donde el modulo hara el deployment.

Aca viene lo interesante: con vuestra cuenta debidamente creada en OpenShift deben agregar estas entradas en el archivo application.conf de la aplicacion en cuestion:

openshift.rhlogin = myuserOpenShift
openshift.password = myPassOplenshift
openshift.application.name = myApp@Openshift

Acto seguido vamos a instalar/desplegar por primera vez nuestra aplicacion:

play rhc:deploy -o

Cuando este comando se procese y al no existir aun la aplicacion en la nube nos preguntara si queremos crearla y si ademas queremos tener un repo en Openshift. A todo le responderemos que SI, ya que por mas que parezca en ese sentido no existe un libre albeldrio. Lo siento ;).

Hasta aqui todo muy bonito pero nuestra aplicacion es standalone y no tiene persistencia de ningun tipo. Entonces con estos comandos :

rhc-ctl-app -a myApp -e add-mysql-5.1 --rhlogin Myuser -p mypass
rhc-ctl-app -a myApp -e add-myphpadmin-3.4 --rhlogin Myuser -p mypass

y con el output de esos comandos se generan estas nuevas entradas en el application.conf

db.url=jdbc:mysql://xxx.xxx.xxx.xxxx:3306/myApp
db.driver=com.mysql.jdbc.Driver
db.user=admin
db.pass=myadminPass

Ya tenemos mysql en nuestro box al cual podemos administrar con phpmyadmin.

Pero la cereza del postre seria que pudieramos cambiar ese feo dominio myApp-myNameSpace.rhcloud.com por algo mas chevere. Para eso agregan un cname tipo host en donde tengan registrado su dominio (en es caso lo hice con GoDaddy), declarando la ip de la url anterior (con un ping ya lo tienen) y desde sus maquinas corran el siguiente comando:

rhc-ctl-app -a myApp -e add-alias mydomain.com --rhlogin Myuser -p mypass

y voila!!! Esto agrega el dominio en vuestra aplicacion. Dicho sea de paso pueden agregar mas de un dominio a una sola aplicacion.

Ok, hasta aqui llego hoy. Para no aturdilos mucho, en la proxima entrega les explico en forma muuuuy sencilla como agregue a esta misma aplicacion el Css Framework de twitter: Bootstrap.

La aplicacion la pueden ver en progreso en Blog’s @DiegoRam

Las mas grande agradecimiento para Sebastian Scarano (@opensas) y Luis Farzati (@luisfarzati) que me dieron una mano terrible en el proceso.

Saludos y comenten.

Iba a hacer una version con acentos, pero que mierda!! el codigo no lleva acentos y, como ya dije en el título de este artículo, soy muy perezoso 😉

.gitignore template file for play framework

Well, this used to be in the code snippets section at play framework’s site, but since the new site for play 2.0, it’s no longer there.

So I decided to write it down here, just to have it at reach, and in case it might be useful for others.

just place this in a .gitignore file

*~
*.swp
.classpath
.project
.redcar/*
.settings/*
.DS_Store
eclipse/*
eclipse/classes/*
precompiled/*
tmp/*
tmp/bytecode/*
test-result/*
server.pid

Play!1 …mas o menos completo (4)

Qué es lo siguiente?
Repasamos conceptos básicos como:
– Vistas (Groovy)
– Templates
– Custom Tags

Vistas (El motor de Groovy)

Bueno, creo que Groovy desaparece en Play2 pero lo voy a ver igual, si te preocupas de ver siempre lo último terminar por no programar nada. Además, después de todo, podemos seguir usando esto mediante el módulo fastergt que encontramos en la web de play.Las vistas es otro de los tres componentes de la arquitectura MVC.
Todas las vistas se encuentran en app/views. Podrás ver las subcarpetas por controlador, así que empezamos con la vista de la primer aplicación creada en app/views/Application/index.html.

Propósito

La capa de la Vista es para mostrar al usuario el estado actual de la aplicación, incluído el contenido de la capa demodelo, una vez que el controlador permita que el modelo haga las actualizaciones. Se va a ver más adelante, pero primero necesitamos entender cómo crear la vista.
La vista puede renderizar en cualquier formato de texto que querramos. Podemos sacar HTML, JSON, XML, RSS, etc, y ellas son toas manejadas exactamente por play de la misma forma. Play viene con Groovy como languaje expression para ayudar a desarrollar la vista, el cual incluye un pequeño sistema de templates.

Sintaxis

Una vista es una mezcla de contenido estático y dinámico. El contenido estático es cosas como tags HTML, o XML. El contenido dinámico se calcula en tiempo de ejecución por el motor de Groovy y puede ser como acceso a los parámetros pasados por el controlador al método render, o tags, comentarios, etc.

Expressions – ${….}

Una Expression es una de las formas más usadas para agregar contenido dinámico a la vista. Una expression simplemente pone los resultados de la expresión a la vista. Un ejemplo de esto es sacar los items pasados a la vista desde el controlador via el método render.

Por ejemplo


<h1>Hello ${myName ?: ‘guest’}!</h1>

El ejemplo tiene contenido estático y dinámico. El código ${myName ?: ‘guest’} es la parte dinámica, el resto es la parte estática.
La expresión consiste en el signo dolar con las llaves ${….}

NOTA: Si una variable contiene cualquier elemento HTML, Play automiáticamente los sacará para prevenir cross-site-scripting. Puedes prevenir este comportamiendo llamando al método de la variable.


${myName.raw()}

 

Tags – #{….}

Como los tags en JSP, el motor de templates de Play tiene un set de tags que pueden usarse para el desarrollo rápido. Básicamente los tags con fragmentos reusables de la Vista. Un tag es representado en una vista usando la almohadilla entre las llaves #{….}
Los tags toman cualquier número de paránetros, pero si el tag solamente tiene un solo parámetro, la convención es que el nombre del parámetro sea arg y el nombre del parámetro puede comitirse cuando agregamos el tag a la vista.
Por ejemplo, el siguiente ejemplo agrega funciones extra disponibles para el usuario, si es administrador usando el tag IF. El tag A es usado para creear hyperlinks. Por supuesto, puedes continuar usando el método estándar <a href />, pero Play agrega esos tags por conveniencia.


<div>
 <ul>
 <li>#{a @Application.index()}Home#{/a}</li>
 <li>#{a @Application.index()}Home#{/a}</li>
 #{if user.admin}
 <li>#{a @Application.index()}Home#{/a}</li>
 #{/if}
 <li>#{a @Application.index()}Home#{/a}</li>
 </ul>
 </div>

Este tag tiene cuerpo debe ser abiero y cerrado, pero el código no ttenga cuerpo puede hacerse así:


#{script ‘jquery.js’/}

Actions – @{….}

Los Actions son una via para que Play renderize lo mas apropiadamente URL cuando cree links para acciones de Controlador, basado en el archivo de rutas (routes files).
Suponga que en tu aplicación tienes que poner una acción llamada logout() en el controlador Application.java, y las rutas quecrearenel archivo crearon un URL para enviar las solicitudes Get a /logout. Sin embargo una segunda opción es usar reverse routing con @{…}


{a @Application.logout()}Logout#{/a}

Cuando la vista es ejecutada, la dirección para la acción logout en el controlador de Application se busca desde el archivo de rutas y la URL apropiada es generada. Esto permite que el URL especificado en el archivo de rutas sea desacoplada desde la vista.
El @{…} generará una URL relativa cuando es ejecutada, si necesitas una URL absoluta (por feed RSS y emails etc), ahí puedes usar la notación @@{….}

Messages – &{….}

Si quieres internacional tu aplicación, puedes usar el archivo de mensajes que viene incluido con play. Los archivos pueden localizarse en el directorio conf/ y el archivo se llama messages.
El archivo contiene una lista de nombre, valores pares (‘nombre de la propiedad’=’valor’), y usando la anotación &{…} poner los mensajes del archivo en la vista.
Veamos un ejemplo


hello=Hola %s!

El %s es una marca para entrada dinámica de datos, y cualquier numero de entradas %s puden usarse en un archivo de mensajes (esto utiliza la misma sintaxis como el formato del método de una clase String, muy usado desde los printf de C).
Para obtener el mensaje y mostrar en la vista, necesitamos usar la notacion ampersand &{…}. Permite tomar el mensaje original Hello World y cambiarlo por el del archivo.

Antes


<h1>Hello ${myName ?: ‘guest’}!</h1>

Después


<h1>&{‘hello’, myName ?: ‘guest’}</h1>

La salida en ambos ejemplos va a ser idéntica. La unica diferencia es que uno está leyendo el mensaje desde el archivo y el otro lee como contenido estático. Observe como la variable myName dentro del tag o mensaje no necesita evaluarse como una expresión (usando el signo dolar).
El archivo (conf/messages) es por defecto para todos los idiomas. Si quieres hacer un sitio multilenguaje necesitas especificar en application.conf que soporte idiomas usando la propiedad application.lang.

Entonces para cada nuevo lenguaje soportado necesitas crear messages.en, messages.es, mensajes.pr, etc etc.

Comments – *{….}*

Como con casi todos los lenguajes, puedes agregar comentarios usando *{….}*

Los comentarios no se evalúan en ejecución, así que los comentarios no van a enviarse al browser (a menos que sean comentarios HTML).
Ejemplo:


*{
 Comentario Increible
 }*
 #{list items:users, as:’user’}
 <li>${user}</li>
 #{/list}

Scripts – %{….}%

Es similar a los scriplets en JSP. Por lo general usar scripts en tu vista es una mala práctica. Si tu código necesita más lógica es mucho mejor hacerlo en el controlador o en un tag para reducir la complejidad de la vista.
Un script permite hacer explresiones mas complejas que las expresiones con las funciones básicas, como declarar variables. Las variables definidas dentro de un script están disponibles para usar dentro de expresiones además de scripts (exactamente igual a scriplets JSP).


*{ crear el fullname de un usuario }*
 %{ fullname = user.firstname + ” ” + user.lastname; }%
 <h1> Bienvenido ${fullname}!</h1>

El script también tiene acceso a objetos implícitos, que permite hacer directamente ciertas cosas como hacer una respuesta escribiendo un objeto.

Templates

Uno de los conceptos claves de Play es reducir la cantidad de trabajo para desarrollar tu aplicación. Una opción común en las aplicaciones web, y que también trae incluida Play, son los templates.
Una vista puede estar hecha por una o varias vistas. Ya usamos template cuando generamos la aplicación por defecto con  new play application.
Un template se usa con el tag extends.


#{extends ‘main.html’ /}
 #{set title:’Home’ /}
 <h1>Hello World!</h1>
 What is your name?
 <form action=”@{Application.sayHello()}” method=”POST”>
 <input type=”text” name=”myName” />
 <input type=”submit” name=”hello” value=”Say hello!” />
 </form>

Las primeras dos líneas son parte de el template. La primer línea dice que la página debe heredar main.html. Podemos encontrar este archivo en app/views.
La segunda línea dice que pondrá la variable title a el valor “Home”.
Si vemos la página main.html podemos ver como la pågina está armada.


<html>
 <head>
 <title>#{get ‘title’ /}</title>
 </head>
 <body>
 #{doLayout /}
 </body>
 </html>

Los valores se setean en la variable title y es obtenida usando el tag #{get}. El tag doLayout en la página main.html es el lugar para sacar  el contenido de la página que ha llamado al template, en este caso el index.html desde la application Hello World.

En síntesis, los conceptos clave son:

  • El tag extends indica qué archivo vamos a incluir en nuestro template
  • El tag set puede usarse para pasar variables entre templates
  • El tag get puede usarse para recuperar variables que usaron el tag set
  • El tag doLayout puede usarse para insertar el contenido de la solicitud de la vista en el template.

Custom Tags

Es posible crear nuestro propio tag.
La ventaja de usar esto es que nos permite abstraer y quitar complejidad de código de la vista en un tag específico.
Un tag simplemente es un archivo template, como todas las otras vistas.

Creando Tags

Para crerar un tag simplemente hacemos un archivo en app/views/tag. El nombre del archivo necesita ser el nombre del tag seguido por el tipo de vista. Por ejemplo, un tag llamado blogPost necesita llamarse blogPost.html.
El código dentro de blogPost es el código producido cuando se llama al tag. Esto puede incluir pasar datos desde el controlador como parte de renderizar argumentos o métodos. Un ejemplo de un post de un blog puede ser como lo siguiente:


<div>
 <h1>${post.title}</h1>
 <p>${post.content}</p>
 </div>

Para llamar el tag, podemos usar la misma notación de tag que usamos para los tags de Play.


#{blogPost /}

Cada vez que blogPost es llamado, esto devolverá el contenido del tag, el cual renderiza los datos desde el objeto post. Esto sin embargo no es particularmente útil respecto a como simplificará la salida del mismo post sobre el objeto post. Lo que nosotros necesitamos para hacer esto es pasar en el post en particular lo que nosotros queremos renderizar.

Parámetros

Para pasar datos en el tag necesitamos agregar parámetros al tag. Otra vez, esto es idéntico a la forma de pasar parámetros en los tags incluídos. El formato para pasar datos es


#{tag paramName: paramValue, paramName2: paramValu2 /}

También, si tiene un solo parámetro, y el nombre del parámetro no es especificado, es automáticamente asignado al parámetro con nombre tag.
Una vez que los parámetros fueron pasados a el tag, podemos tener acceso al contenido. En el código del Tag, los parámetros son accesibles desde adentro del tag como variables con formato de guión bajo ‘_’, siguiendo por el nombre del parámetro. Asi, arg puede convertirse en _arg y post a _post.
Si nosotros por lo tanto el tag del ejemplo previo del blog, nosotros podríamos pasar el post en el tag de la siguiente manera.


#{list items:posts, as:’post’}
 #{blogPost post /}
 #{/list}

Esto muestra una lista de post iterados en un tag de lista, y item individual del post es renderizado usando nuestro blogPost. Sin embargo podríamos tener que cambiar nuestro tag ligeramente, como nosotros no especificamos un nombre para nuestro parámetro; necesitamos leer la variable desde el parámetro arg por defecto. Nuestro tag quedará


<div>
 <h1>${_arg.title}</h1>
 <p>${_arg.content}</p>
 </div>

Tag Body

Para algunos tags no es suficiente pasar datos usando parámetros. Un buen ejemplo es el tag list que usamos para iterar sobre la lista de post de nuestro blog. Necesitamos especificar contenido para mostrar entre la apertura y el cierre del tag (llamado tag body).


#{mytag}
 <h1>this is the body the tag</h1>
 <p>some more body</p>
 #{/mytag}
 Para obtener tu tag para renderizar el cuerpo del tag, podemos usar el tag especial doBody.
 <div>
 #{doBody /}
 </div>

Note que el cuerpo del tag puede ser mezclado, así que puedes usar ambos parámetros en el cuerpo del tag.

Objetos Implícitos

Hay numerosos objetos especiales que están disponibles dentro del template en la vista.

  •   session – dentro del template obtiene acceso a la sesión del objeto
  •   flash – obtiene acceso al flash scope. Este objeto es utilizado para controlar la duración y vida de una consulta.
  •   request – es la consulta que se envía desde el browser al servidor se play.
  •   params – es un objeto que contiene parámetros que son enviados con el reques.
  •   play – es la referencia al objeto play.Play. Ésta es la referencia clave de muchas configuraciones en una aplicación play, como los módulos, rutas, plugins, classpaths, tags, etc.
  •   lang – es el lenguaje del usuario actual.
  •   messages – una referencia al mapa de mensajes, aunque en la mayoría de los casos deberías usar &{…} para mostrarlos
  •   out – es la salida del output stream que está siendo escrito automáticamente por nuestra vista y que será enviada al cliente.

En la mayoría de los casos es raro que necesites usar estos objetos.

Java object extensions

Cuando usamos objets en la vista de la aplicación, Play automáticamente agrega métodos para las clases de Java. Estos no existen en la clase original, así que si chequeas el código fuente (o Java API) no estará allí, pero en tiempo de ejecución esos métodos serán agregados para hacer nuestras vistas fáciles de escribir.
Un ejemplo es el método format que se agrega a java.lang.Number. Esto nos permite fácilmente dar formato a los números en la vista, sin tener que hacer el formateo en el controlador, en el modelo o en scripts.
Shopping Cart: Total Price £ ${cart.total.format(‘##,###.##’)}
Aquí hay un largo número de extenciones incluidas con play framework. Son listadas, pero se recomienda chequear el API por las actualizaciones. Para encontrar la lista completa lea el JavaDocs API de la clase play.templates.JavaExtensions
Algunas extensiones son:

  •   addSlashes
  •   asdate
  •   camelCase
  •   capAll
  •   capFirst
  •   capitalizeWords – cut
  •   divisibleBy
  •   escape
  •   escapeHtml
  •   escapeJavaScript – escapeXml
  •   format
  •   formatCurrency – formatSize
  •   last
  •   noAccents
  •   pad
  •   page
  •   pluralize
  •   since
  •   slugify
  •   urlEncode
  •   yesno

Creando una Extensión Customizada

Si la lista disponible no nos permite formatear como nosotros quisiéramos, es posible crear tu propia extensión. Para hacerla tienes que crear una nueva clase de Java y extender de play.templates.JavaExtensions.

Un ejemplo de extensión que tomaría los 2 primeros caracteres de un string.


package ext;
 public class MyExtension extends play.templates.JavaExtensions {
 public static String chop(String s) {
 return s.substring(2);
 }
 }

En la vista lo llamaríamos así:


<h1>Hello ${myName.chop()}!</h1>

Una custom extension debe tener un método public static, extendiendo de la clase JavaExtension y debe retornar un String (después de todo es para generar aplicaciones web no?).
Cuando Play arranca, chequea todas las clases que extienden de JavaExtensions. Los primeros parámetros de un método identifica el tipo de objeto que la extensión puede realizar. Y podemos agregar parámetros que permitan cambiar, por ejemplo, el número de letras a devolver, etc. La signatura debería ser


public static String chop(String s, int size) {
 return s.substring(size);
 }

En la vista pasaríamos el tamaño cuando se llama al método chop


<h1>Hello ${myName.chop(2)}!</h1>

Nota. Debido que las custon extensions son detectadas cuando arranca el servidor, debemos reiniciar el server para que esté disponible en nuestra aplicación.

@wfranck

Play!1 …mas o menos completo (3)

Qué es lo siguiente?
Repasamos conceptos básicos como:
-Request
-Render
-Redirect
-Anotaciondes en el controlador
-Sesión de Usuario

Response

HTTP está basado en un modelo request/response (solicitud/respuesta).
Las respuestas pueden estar vacías pero debe hacerse por alguna vía para confirmar que la consulta llegó. En play, una respuesta se envía (por Render) en métodos o redireccionando a una URL específica.

Render

Play tiene un numero de métodos de renderizado que pueden usarse para enviar devuelta las respuestas a el cliente. Estos son:
– renderText()
Para retornar respondiendo con un texto plano.
– renderXML
– renderBinary()
Puede tomar un archivo o un InputStream como un parámetro para devolver contenidos por la llamada de la aplicación. También puede especificar los nombres de archivos con el InputStream para especificar los valores que se mostrarán en la ventana cuando descargue.
-renderJSON()
Podemos usarlo desde un string JSON, un string pre-preparado o un objeto java. Si se usa un objeto, deberá primero serializarse a JSON y luego devuelto.Sin embargo, el método comúnmente más usado es
-render()

El método render renderiza un template Groovy, el cual básicamente permite contruir un HTML a full (y XML, JSON, etc) páginas usando templates para reducir la cantidad de código duplicado. Cuando escriba sobre las Vistas se va a ver esto con detalle.
Más adelante se va a explicar como funciona, ahora solo veamos como trabaja.

package controllers;
 import play.mvc.*;
 public class Application extends Controller {
 public static void index() {
 render();
 }
 public static void sayHello(String myName) {
 render(myName);
 }
 }

El método render es lo suficientemente inteligente como para saber cual acción llamamos. Como en el ejemplo, cuando es llamado desde el metodo index sabe que tiene que renderizar el index.html en la carpeta Application (porque Appliocation es el nombre del controlador).
El segundo método sayHello renderizará el sayhello.html en la misma localización. Siempre y cuando, en este método también le incluyamos datos adicionales. Debemos parsear los argumentos myName en la página sayhello.html. El método renderizado puede tener cualquier número de argumentos, pero solamente renderizar variables locales.
Si no queremos pasar datos a la vista por esta vía, o necesitamos pasar argumentos que no son variables locales, hay otra opción. Directamente accedemos a la variable renderArg Map para agregar argumentos usando el método put.

renderArgs.put(“clave”, elValor);

Si no queremos que renderize el template especificado por nombre del método de la acción, podemos sobreescribir el template en una de dos maneras. Primeramente podemmos llamar al método renderTemplate(), que toma el nombre del template como primer parámetro y los parámetros restantes son los argumentos pasados en el template. Como alternativa, simplemente podríamos llamar a render() y  setear el template como el primer parámetro.

public static void sayHello(String myName){
 render(“Application/dontSayHello.html”, myName);
 //o también aquí podríamos hacer
 //renderTemplate(“Application/dontSayHello.html”, myName);
 }

NOTA: algo importante para tomar conciencia de que todos los métodos render es que una vez que llamamos al método render, además que corre el código de la acción. El render inicia que el evento que devuelve a la aplicación (el navegador) y además no ejecuta ningún otro.

public static void sayHello(String myName){
 render(myName);
 //cuidado: este codigo jamás será ejecutado
 Logger.log(“Hola render!”);
 }

Redirect

Un elemento común de HTTP es la podibilidad de redireccionar, por ejemplo redireccionar un request a Twitter.

Por ejemplo si queremos hacer un servicio acortador de URL (URL shortening service), podríamos tener algo parecido a

public static void performRedirect(String shortURL){
 URLPair url = URLPair.find(“byShortURL”, shortURL).first();
 redirect(url.longURL);
 }

Hay algunos lugares donde Play puede redireccionar automáticamente. Imagina que tu aplicacion tiene dos nuevas funciones.
– crear un nuevo artículo
– mostrar el nuevo artículo
Luego que el artículo se crea podrías querer mostrar el artículo inmediatamente. Puedes hacer algo como lo siguiente.

public static void show(Long id) {
 //Cargar el artículo desde la base de datos
 Articulo articulo = Articulo.findById(id);
 render(articulo);
}
 public static void create(Articulo articulo) {
 //primero guardar el articulo a la base de datos
 articulo.save();
 //ahora mostrar el articulo
 show(articulo.id);
 }

Cuando corra la acción, pasará lo siguiente:
– Play hace que el método show sea llamado, el cual en sí mismo es una action, e intercepta el request (consulta), previniendo que esto sea ejecutado inmediatamente.
– Play calcula qué URL necesita ejecutar la acción show() con el id específico.
– A HTTP 302responde lo enviado a le browser con el header Location:/article?id=12. (Asumiendo que el route para método show del articulo es /articulo y el id generado por el guardar en este evento es el 12).
– El navegador recibirá el 302 redirect, y la solicitud GET /articulo?id=12
– El método mostrar es ejecutado normalmente.

Anotaciones de Controlador (Controller Annotations)

Los Controladores de play vienen con un número de anotaciones que permiten que un evento de una acción de un controlador pueda ser tomado, similar al concepto de Filtros en Servlet. Estos son:
– @Before
– @After
– @Finally

Un interceptor necesita ser static, pero no public.

@Before

Si un interceptor está hecho con esta anotación, indica al framework que antes que cualquier acción se ejecute en este controlador, el interceptor debería ser invocado. Esto puede ser útil por algunas cosas, como la carga de algunos ítems de configuración, o para autenticar a los usuarios que acceden a las acciones en el controlador.

Ejemplo de una autneticación

@Before(unless={“login”,”notauthorised”})
 static void checkAdmin(){
 String usr = session.get(“user”);
 if (usr == null){
 login();
 }
 }
 else {
 User user = User.find(“byUsername”, usr).first();
 if (!user.isAdmin) {
 notauthorised();
 }
 }

Lo anterior chequea si el usuario está logueado chequeando la sesión del objeto, y sino los carga desde la base de datos chequeando si están autorizados.

La anotación @Before puede ser usada por su propia cuenta, sin ningún tipo de soporte pero en este ejemplo te darás cuenta que tiene un parámetro menos. Este parámetro (que puede ser usado con @After y también @Finally) permite excepciones para interceptar. Esto es práctico porque si no especificamos las excepciones (exceptions), podríamos estar en un loop infinito si falla el chequeo Admin, porque no podríamos redireccionar a la página de login, y esto podría llamar a checkAdmin. Sin embargo, nuestro ejemplo no intenta chequear si el usuario es admin si el login o nonauthorised actions fueron llamadas.

@After

La anotación @After trabaja de forma muy similar a @Before, excepto que esto se ejecuta luego que se llama cualquier acción, pero antes que la vista sea renderizada. Esto podría usarse para cargar cualquier item que sea necesario antes de que la vista sea creada.

@Finally

La anotación @Finally es ejecutada una vez que la acción fue completada, y la vista ha sido renderizada y la respuesta es enviada devueta al browser. Esto puede ser usado para poner en orden sabiendo que no tendrá efecto con lo que habrá renderizado para la respuesta.

Considera el siguiente ejemplo de anotaciones que extiende de el controlador Hello World.

public class Application extends Constroller {

 @Before
 static void log0() {Logger.info(“before: “+ response.out.size());}
 @After
 static void log1() {Logger.info(“after: “+ responses.out.size());}
 @Finally
 static void log2() {Logger.info(“finally: “+ response.out.size());}

public static void index() {
 Logger.info(“in index action”);
 render();
 }

public static void sayHello(String myName) {
 render(myName);
 }

}

Serás avisado porque agregamos 3 interceptores y un mensaje info para la acción index antes del método render(). SI ahora en el browser mostramos la página index y vemos el log (en consola) veremos que:
– La anotación before aparece primero y responde que el tamaño es 0;
– El mensaje que agregamos en la acción index se muestra luego;
– La anotación after se muestra tercero, luego de index, con la resuesta deltamaño 0, como el response aún no ha sido generado.
– Finalmente esto se muestra a lo último con el reponse size en 706 (bytes) como la salida fue renderizada y enviada al browser.

La Sesión

Una de las grandes diferencias entre Play y la mayoría (no todos) los otros Java web framewoks disponibles, es que este no permite el uso de un objeto sessión del lado del servidor. En la Servlet API, el objeto session es un objeto que está en la memoria del servidor donde puede ser guardado entre peticiones a el servidor, y mantener en memoria durante la session.
Uno de los grandes defectos es que el servidor queda offline (bajo mucha carga, falla del sistema u otra cosa) los datos del usuario se pierden y en la mayoría de los casos muestra un mensaje de error.
Play fomenta el “no guardes nada” en el desarrollo de aplicaciones web. Hay muchas ventajas en esto, pero no menos que hace fácil escalar tu aplicación sin preocuparte de las “sticky sessions” en el balance de carga.
Sin embargo puedes ver que hay un objeto session disponible desde el Controller. Esto permite guardar alguna información del usuario que puede estar en más qeu una simple página, pero esto se guarda del lado del cliente en una Cookie, mas que en la memoria del servidor, permitiendo no arrastrar ninguna arquitectura para mantener.
Ahí hay otro objeto disponilla llamado flash. Este trabaja en lo mismo como el objseto session que guarda en la cookie, excepto esto exista para el valor de la siguiente consulta.
Debe saber que esas Cookies están limitadas a 4Kb y que son devueltas progresivamente coom parte del HTTP request/response, únicamente puede ser texto.

@wfranck

Play!1 …mas o menos completo (2)

Qué es lo siguiente?
Lo siguiente es seguir con conceptos como:
-Modelo MVC y sus capas
-HTTP Routing
-El Controlador

El Modelo MVC

El MVC (Modelo-Vista-Controlador) es un patrón para construir aplicaciones web. El propósito es separar las diferentes capas del sistema independizando el desarrollo, testing y mantenimiento. El Modelo es solo la representación de datos.
La mayoría de las aplicaciones web con bases de datos agregan allí la persistencia.

La Vista es el responsable de confeccionar la presentación de nuestra aplicación al usuario, como podría ser, por poner un ejemplo, un formulario HTML. Esto también podría ser HTML, XML, JSON o imágenes. La vista podría consumirse desde un teléfono, una computadora o podría ser un XML para consumirlo desde un API.

El controlador responde a eventos (por lo general de acciones del usuario  desde la vista) o procesos que, podrían ser invocados por cambios en el modelo.

HTTP Routing

El “ruteo” de la aplicación se configura usando un archivo con las rutas que se encuentra en el directorio “conf” de tu aplicación.

Propósito

El objetivo del archivo “conf/routes” es permitirle a play decidir qué controlador será el encargado de atender las solicitudes o requerimientos (HTTP request) que recibe.

Sintaxis

El archivo contiene 3 elementos principales. El primero es el método HTTP (puede ser GET o POST), el segundo elemento es el URI (como /register) y el último elemento es la clase java controlador y el nombre del método (como Application.index).
El último elemento es opcional si indicamos argumentos estáticos (static arguments) y/o especificamos el tipo de contenido (content type).

También es posible agregar comentarios usando hash (#). Un ejemplo:

# Home
 GET     /                                        Forums.index

# Registration/Authentication
 GET     /signup                                  Application.signup
 POST    /signup                                  Application.register
 GET     /login                                   Application.login
 POST    /login                                   Application.authenticate
 GET     /logout                                  Application.logout
 GET     /signup/{uuid}                           Aplication.confirmRegistration
 GET     /confirmation/{uuid}                     Application.resendConfirmation

# Forums
 POST     /forums                                 Forums.create
 GET      /forums/{<[0-9]+>forumId}               Forums.show
 POST     /forums/{<[0-9]+>forumId}/delete        Forums.delete

# /public
 GET      /public                                 staticDir:public

# Catch all
 *        /{controller}                           {controller}.index
 *        /{controller}/{action}                  {controller}.{action}

Este es un ejemplo bastante completo en que se pueden ver las 3 partes del archivo de configuración, los diferentes métodos HTTP usados, las rutas con elementos dinámicos incluidos y expresiones regulares (en la dirección de {<[0-9]+>forumId}) y también los controladores.

Métodos

Play soporta la especificación HTTP. Si desear que tu ruta permita cualquier método puedes usar *. Los valores válidos para usar en la primer parte son:
– GET
– POST
– PUT
– DELETE
– HEAD
– *

Si quieres tener disponible varios métodos para una URI en particular puedes hacerlo. Esto permite tener un GET y un POST en una misma URI y play responda llamando a distintas acciones según el método HTTP de la solicitud.

Route URI

El route URI es la segunda parte del proceso, poniendo a la par la solicitud HTTP y el controlador. La primer parte de los métodos HTTP y la segunda del patrón URI. Si la solicitud HTTP (HTTP request) encuentra una entrada de URI, el controlador correspondiente será invocado.

Ejemplos:

#ejemplo sencillo
GET        /signup                               Application.signup

#dirección absoluta exacta
GET        /signup/{uuid}                        Application.confirmRegistration

#dirección mapeada dinámicamente
GET        /signup/{<[0-9]+>forumId}             Forums.show

En este caso la expresión regular aceptará únicamente números y mapea los números recibidos en la URI como el parámetro forumId que será recibido por el método show en la clase Forum  (clase que es de tipo controlador obviamente).

Esto hace posible tener varios elementos dinámicos en la URI. Consideremos una aplicación de fotos que organiza las fotografías en albums. La URI puede ser usada para mostrar fotografías desde un álbum en particular. Quizás pueda ser similar a lo siguiente:

GET        /album/{albumId}/photo/{photoId}    Photo.show

El método show de la clase Photo debería ser invocado pasando el albumId y photoId como parámetros del método. Nosotros podríamos incluir una expresión regular para ambos elementos (albumId y photoId) para asegurar que solo puedan tomar valores numéricos.

Como puedes ver, el archivo de ruteo, rutas, routing o como quieras llamarlo, puede llegar a ser un poco sofisticado aunque no deja de ser sencillo para el desarrollo. Solo debemos recordar que una URI estará compuesta por claseControlador/nombreDelMétodo

NOTA: para play los “métodos de acción” (action methods) son métodos públicos, estáticos, que retornan void, pertenencientes a una clase que extienda Controllers. Estos son requisitos necesarios para que el “ruteador” pueda vincular el pedido HTTP con la acción del controlador.

Argumentos Estáticos

Una característica opcional del archivo de rutas es la posibilidad de agregar argumentos estáticos para los métodos que apuntamos en un controlador, lo cual nos permite reutilizar código simplificando el archivo de rutas.

Por ejemplo el usado recién:

GET        /album/{albumId}/photo/{photoId}    Photo.show

Si buscamos que por defecto el álbum empiece a mostrar con la primer imagen, podemos reutilizar el mismo controlador indicando así:

GET        /album/{albumId}                    Photo.show(photoId:1)

Este método recibe dos parámetros: uno es estático (el photoId que colocamos nosotros por defecto) y el otro es el que se tomará dinámicamente de la URI.

Content Types

Por efecto, cuando Play recibe una solicitud chequea el header HTML y responde con el mismo formato del archivo que lo solicitó; si la solicitud llega de un html responde html.

Si estamos buscando RSS con los mismos datos del html solo debemos especificar el formato devuelto:

GET     /recent/rss         News.recentStories(<span style="color: #008000;">format:’rss’</span>)

Prioridad en las Rutas (Route Priority)
El orden de prioridad es de arriba hacia abajo. Cuando una solicitud es recibida, éste lee el archivo de rutas y la primera encontrada invoca al controlador.

Contenido Estático

Para procesar rápido las consultas y facilitar el mantenimiento de la aplicación, el contenido estático se mantiene en un mismo lugar, separado del contenido dinámico que varía entre consultas.
El contenido es localizado en un directorio público, como las imágenes, js y css.

GET        /public                staticDic:public

CONTROLADOR

El Controlador es una de las partes centrales de una aplicación Play como parte del modelo MVC. Todos los controladores de una aplicación se encuentran en app/controllers del directorio de tu aplicación.

Propósito

El propósito es unir el modelo de dominio y los eventos que nos llegan como peticiones HTTP. El controlador no se encarga de la lógica de negocios. Esto está a cargo del modelo. En cambio el controlador recibirá el evento, leerá los parámetros que le llegarán junto con el evento y ejecuta las acciones necesarias sobre el modelo. Una vez completado esto, el controlador retornará la información correspondiente a la vista para que despliegue los resultados a la aplicación que generó el evento, que por lo general es el browser del usuario.

Si lo comparamos con otros frameworks, un controlador podría ser pensado como los HTTP Servlets de J2EE, o en Struts podría ser equivalente a un Action object.

Creando un controlador

Un controlador es una clase Java que extiende de play.mvc.Controller, y que contiene una cantidad de métodos que representan acciones. Cada acción es la vía que tiene el controlador para responder a los eventos generados por pedidos HTTP y tomar las acciones correspondientes.

NOTA: La acción en una clase controlador debe ser public, static y retornar void.

Cuando creas una nueva aplicación en Play, por defecto tendrás un controller llamado Application.java. Contiene un método simple (una action), la cual tan solo renderiza la índex page de la aplicación. La habrás visto en la aplicación que play crea por defecto.

Quizá no haya mucho que destacar salvo que la clase de tipo controlador extiende de play.mvc.Controller. También, las acciones (acedidas según el archivo de rutas) deben ser declaradas public y static. Si no lo haces así, las peticiones de HTTP (HTTP request) no podrán set “ruteadas” correctamente hacia las acciones.

Parámetros

Usualmente, nuestros controladores percisarán parámetros a ser pasados por el usuario para cumplir su cometido..

Básicamente hay tres formas de hacer esto:

  • como parte de una consulta en un string, como con /article?id=123
  • como parte de un body request (si un formulario lo envía usando POST)
  • como parte de la URI, como con /article/123

Por ahora solo importa destacar que como se muestra en el último caso, Play ya trae resuelto esto mapeando los objetos y haciendo las llamadas con esos parámetros.

Hay dos vías que puedes utilizar cuando quieras trabajar con mapeo de parámetros.

  • Parameter map

La primera vía para usar los datos es para trabajar directamente con la variable params. La variable es definida en la super-clase Controller, así que tu podrás tener acceso directo a ella. Para acceder al parámetro, solo necesitas llamar al método get del params Map object, y pasar el nomrbe del parámetro con el que deseas trabajar. Esto es similar a hacerlo con HTTPRequest con Servlets.

String id = params.get(“id”);

y ahora viene la frase… chan chan chan: Play as always does a little bit more. 😀 ja, toma!
Con las solicitudes (request), Play puede convertir automáticamente los datos en un tipo de objeto adecuado. Todos los datos pasados vía
HTTP son texto. En nuestro ejemplo un Id de artículo pasa por ahí, es un numérico. Así que podemos pedir que Play convierta el parámetro automáticamente a un Long agregando el tipo al método get.

Long id = params.get(“id”, Long.class);
  • Action method parameters

Si se agrega un parámetro al método de la acción, siempre y cuando sea el mismo nombre que el parámetro HTTP, Play automáticamente rellenará los datos a su correspondiente parámetro de Java.
Por ejemplo, si el browser solicita la pagina /article?id=123 y el archivo de rutas tiene el método show(). Para levantar el id, nosotros solamente necesitamos el parámetro llamado id del método en cuestión.

public static void show(Long id){
 render(Article.findById(id));
 }

Aquí, el valor HTTP del parámetro id debería automáticamente castearse a Long para llenar el id del paramámetro Java.

HTTP to Java Binding

Play maneja el mapeo de todo slos tipos primitivos de java y sus equivalente en objetos (como Long, Boolean, Float, etc). Como siempre también maneja algunos objetos más, incluyendo
-Fechas
-Archivos
-Arrays
-Custom objects (POJO)
-JPA

Fechas

//Acá este terrible problema, a veces cansa no? el manejo del formato fecha y los nulos es lo peor que te puede pasar como programador… bueno, tenía que llorar un rato.

Tenemos que seguir alguno de la lista de patrones para que a Play le alcance su inteligencia y pueda mapear las fecha correctamente correctamente

 - yyyy-MM-dd’T’hh:mm:ss’Z’ // ISO8601 + timezone
 - yyyy-MM-dd’T’hh:mm:ss” // ISO8601
 - yyyy-MM-dd
 - yyyyMMdd’T’hhmmss
 - yyyyMMddhhmmss  - dd’/‘MM’/’yyyy
 - dd-MM-yyyy
 - ddMMyyyy
 - MMddyy
 - MM-dd-yy
 - MM’/‘dd’/’yy

Archivos

Es muy Simple. Dese la vista, una solicitud viene de varias partes/formularios como normalmente se usa para subir archivos en una aplicación web. Como siempre, una vez que el archivo llega al lado del servidor, esto puede ser mapeado directamente a un objeto Archivo.
Un ejemplo:

public static void upload(File photo) {
 // manipulate the uploaded File
 // …
 // save the photo to the DB get an ID
 // …
 show(id);
 }

Cuando subimos un archivo Play lo guardará en un directorio temporario. Al final del request Play borrará el archivo. Por lo tanto si quieres concervar el archivo vas a necesitar guardarlo en algún lugar.

Arrays

Los arrays pueden pasarse como parámetros HTTP usando sintaxis como la siguiente:

/article?id{0]=123&id[1]=456&id[2]=789

Esto es perfectamente válido en HTTP, y puede ser muy práctico. Por ejemplo podemos usarlo para mostrar multiples artículos en una sola página. Para recuperar los Ids sobre un array, podemos usar los estándares de notación de array o cualquiera de las colecciones de Java de los que disponemos para usar sobre las acciones de nuestros métodos.

public static void show(Long[] ids){
 …
 }

Ó, una colección:

public static void show(List<Long> ids){
 …
 }

Custom Objects (POJO)

Es posible usar parámetros HTTP y los viejos objetos Java (POJO). Mediante el uso de notación de objectname.variablename, nos permite pasar una gran cantidad de datos a la acción, mientras que lo mantenemos en sintonía con simplicidad del método.

For ejemplo, si a nuestro site suscribimos a un usuario nuevo, podríamos enviarlo en una solicitud en el objeto, como:

addSuscriber?user.name=Walter&user.login=wfranck&user.password=secreta

La sintaxis en la acción del método debe ser como:

public static void addSuscriber(User user){
 …
 }

También es posible tener objetos dentro de objetos. Agregando algunos puntos a la notación. Por ejemplo:

addSuscriber?user.name=Walter&
user.login=wfranck&
user.password=secreta&
user.address.street=Alguna+Calle&
user.address.postcode=B1663IHH&
user.address.country=UK

En el ejemplo anterior, el objeto User también contiene un objeto Address llamado address (recuerda que hacemos el binding via nombre de la variable) y la dirección del objeto tiene al menos 3 variables llamadas street, postcode y país.
Si allí hay otras variariables que no pasadan parámetro, estas se dejan como valores por defecto.

JPA

El API estándar de persistencia en Java, en pocas palabras es el camino simple para guardar datos en bases de datos con el modelo orientado a objetos.
El paquete de JPA es muy similar a lo que todos conocmos. La diferencia con JPA radica en si facilitamos un id en como parámetro HTTP, Play se encarga en traer el objeto JPA desde la base de datos, y luego setear los parámetros restantes desde los parámetros HTTP. Por lo tanto puedes guardar el objeto con los cambios realizados llamando con save() en el objeto JPA, sin tener que realizar alguna lógica más para cargar y actualizar el objeto antes de guardar en la base de datos.

@wfranck

Play!1 …mas o menos completo

Introducción a Play! Framework

Play es un framework que nos permite crear aplicaciones web de una manera simple y ágil, y al mismo tiempo evitar la burocracia comúnmente asociada a los frameworks web de Java.

Hace varios meses me propuse comenzar a explorar esta herramienta. Mientras lo hice fui tomando notas y escribiendo cosas que me resultaban de interés. Hoy las comparto con ustedes, esperando que les resulte de utilidad para dar sus primeros pasos con Play.

Algunas cosas que te gustarán de play

-Guardar y Recargar. Con Play no necesitas guardar tus cambios, recompilar, hacer un nuevo package y volver a desplegar tu aplicación. Es tan fácil como hacer ctrl+s y F5. Si no hay errores simplemente refrescamos el contenido; si no muestra la línea donde cree que nos hemos equivocado en el propio explorador (Find errors fast).

-Stateless model. El creador del framework nos muestra que no es necesario guardar estado en la sesión, permitiendo escalar fácilmente.

– Viene con templates basados en Groovy para simplificar el mantenimiento y hacer la lectura más fácil (la implementación de Groovy está cambiando en Play!2)

-Java Puro. Por eso puedes programar utilizando cualquier editor de texto hasta los 3 IDE’S más usados.

– Out of the Box, ready to go. La descarga de Play pesa alrededor de 40MB , y contiene todo lo necesario para empezar a desarrollar, incluido Hibernate, OpenID, MemCached.

Instalación

Aquí no hay nada interesante (¡y eso es bueno!), solamente descomprimir el archivo en un directorio y ejecutar por consola: play

Creando y arrancando una aplicación

Escribimos por consola:

play new nombreDeLaApp

… y play nos pedirá que le asignemos una suerte de título a la aplicación.

Con eso se crea el esqueleto de una aplicación de play completa, más adelante voy a describirlo.

Corremos la aplicación:

play nombreDeLaApp

Abrimos un navegador y vamos a http://localhost:9000

En esto Play generó la estructura básica y mostrará la paǵina de presentación de la aplicación explicando qué está haciendo.

Escribiendo una Vista
Vamos a modificar la aplicación generada y personalizar la vista.

Vamos a la carpeta de la aplicación generada en nombreDeLaApp/app/views/Application y abrimos index.html encontrando el siguiente código:

#{extends ‘main.html’ /}
#{set title:’Home’ /}
#{welcome /}

Borramos la línea #{welcome /}, que es el tag que utilizar play para mostrar el mensaje de bienvenida por defecto.

Ahora vamos a editar esto escribiendo allí mismo <h1>Hola Mundo</h1>

Refrescamos en el navegador y vemos los cambios.

Ahora en el mismo lugar vamos a agregar un formulario con un campo text y un botón submit para preguntar el nombre al usuario. Debería quedar algo así:

#{extends ‘main.html’ /}
#{set title:’Home’ /}
<h1>Hello World!</h1>
What is your name?
<form action=”@{Application.sayHello()}” method=”POST”>
  <input type=”text” name=”myName” />
  <input type=”submit” name=”hello” value=”Say hello!” />
</form>

Si refrescamos nos encontraremos con un error porque el destino Application.sayHello() que busca el método post no existe.

Como estamos en desarrollo nos va a decir que hubo un error pero cuando esto pase a producción va a llamar al estándar HTTP 500 error (que podemos personalizar). Tranquilo que el usuario final no va a ver tu código.

Creando el Controlador

El controlador es esa parte del MVC que contiene la lógica de la aplicación. Típicamente la lógica y las reglas de negocio hacen que tu aplicación responda a las entradas del usuario. Nuestro controlador debería responder al nombre que tiene en el formulario.

Por defecto play crea un controlador Application.java en nombreDeLaAplicación/app/controllers/. Ahora necesitamos un método que sepa responder a Application.sayHello()

Nuestro controlador Application debería quedar así:

package controllers;
import play.mvc.*;

public class Application extends Controller {

  public static void index() {
    render();
  }

  public static void sayHello(String myName) {
    render(myName);
  }
}

Si guardamos el archivo y refrescamos el navegador el error debería haber desaparecido, y debería poder verse la aplicación Hola Mundo esperando que ingresemos algo.

Si hacemos click en el botón tendremos otro error diciendo que Application/sayHello.html no existe. Tenemos que ver el código que hicimos para entender por qué nos da el error.

Cuando clickeamos en el botón para enviar nuestro nombre en el formulario, esto envía los datos en el campo de testo al método sayHello en el Controlador. Play reconoce que el nombre del campo de texto en el formulario fue llamado ‘myName’, asi que automáticamente rellena los datos que ingresamos en la variable myName.

El código render(myName) intenta mostrar la página HTML para renderizar el resultado. Por defecto, el método render muestra un archivo HTML con el mismo nombre que el método desde donde es llamado, así en este caso es sayHello.html. Sin embargo, hasta el momento solo creamos una página  (la index). Entonces solo necesitamos crear el template sayHello.html

Ahora vamos a helloworld/app/views/Application y creamos un archivo llamado sayHello.html y ponemos el siguiente código.

#{extends ‘main.html’ /}
#{set title:’Home’ /}
Hello ${myName}!

Refrescamos el navegador y ya está completo, tenemos nuestra primer aplicación Play Framework. (en 12 líneas de código)

sources en github

@wfranck