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!

Advertisements

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

%d bloggers like this: