FactoryPal: New Scala framework for creating objects as test data. Say no to Fixtures and Mocks.

by @mgonto, original article can be found here

Hey everyone! First of all, if you want to read the original article please go to this link

FactoryPal is a scala framework that lets you create objects as test data. All you have to do is define the templates for each of the classes that you want FactoryPal to create objects from. After that, FactoryPal takes care of the rest.

Have you ever heard of factory_girl a super cool Ruby framework? Well, FactoryPal is factory_girl for Scala. It is pretty similar in its use. The difference is that FactoryPal is 100% type safe, which all of us Scala people love.

Here is a link to Github for the anxious https://github.com/mgonto/factory_pal

How do we use this?

FactoryPal is a singleton object where you can register all of the templates. For example, you can define a template as follows:

FactoryPal.register[Person] { person =>
    person.name.mapsTo("gonto") and
    person.age.isRandom
}

In this example, we register a new template for class model. If we try to set a value for a property that Person doesn’t has, your project won’t compile. If you try to set a value to a property that isn’t the type of that property, the project won’t compile either. Pretty cool huh? This was possible thanks to Scala Macros and Dynamic, two features added in the latest Scala 2.10 RC release.

For the time being, there are 3 supported operations on a field template.

  • mapsTo: This sets a certain specific value to that property.
  • isRandom: This sets a random value based on the type of the field. I’ve created some implicit randomizers for common objects (String, Long, Int, Double, etc.) but you can create your own. This is pretty similar to Ordering[T] used in List.
  • isAnotherFactoryModel: You tell FactoryPal that this is an inner object that can be constructed with another template of FactoryPal. For the time being, there can only be one template for each class. I’m going to change this very soon.

After we created the template, we can instantiate objects of that template as follows:

val person = FactoryPal.create[Person]

The create method has another overload that lets you add some field overriders for certain test. For example you can do the following:

val person = FactoryPal.create[Person] { (person : ObjectBuilder[Person]) =>
    person.age.mapsTo(45) alone
}

And that’s it. That’s all you need to know to use this.

How can I add this to my project?

This is an example configuration for Build.scala for your SBT project :). There’re only snapshots for now as Scala 2.10 is not yet final. Once it’s, I’m going to make a release.

import sbt._
import sbt.Keys._
 
object ApplicationBuild extends Build {
 
  lazy val root = Project(
    id = "factory_pal_sample",
    base = file("."),
    settings = Project.defaultSettings ++ Seq(
      name := "factory_pal_sample",
      organization := "ar.com.gonto",
      version := "0.1",
      scalaVersion := "2.10.0-RC3",
      scalacOptions += "",
      licenses      := ("Apache2", new java.net.URL("http://www.apache.org/licenses/LICENSE-2.0.txt")) :: Nil,
      libraryDependencies ++= Seq(
       "org.scala-lang" % "scala-compiler" % "2.10.0-RC3",
       "ar.com.gonto" % "factory_pal_2.10" % "0.1-SNAPSHOT",
       "org.scalatest" % "scalatest_2.10.0-RC3" % "1.8-B1" % "test"
      ),
      resolvers ++= Seq(
         "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/",
         Resolver.url("Factory Pal Repository", 
          url("http://mgonto.github.com/snapshots/"))(Resolver.ivyStylePatterns)
      )
    )
  )
}

Take a look at the dependency and the repository!

What does it use internally?

Internally, this framework uses Scala Macros, Dynamic and the new Reflection library provided by Scala 2.10.

Next Steps

The next things I want to do are:

  • Add the posibility to have multiple templates for one Class
  • Add template inheritance
  • Add helpers to use this with ScalaTest and Specs2. For the moment, you can create the templates in the before.

For more information or to take a look at the code go to Github

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!

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

Let’s Play! in the cloud

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

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

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

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

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

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

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

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

Have fun playing on the cloud!

Play Framework posted values revisited

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

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

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

app/views/index.scala.html

@(message: String)

message: @message <br />

<h2>Scala form</h2>

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

<h2>Java form</h2>

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

And the following routes file:

conf/routes

# Home page
GET     /                         controllers.Application.index

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

With java, accesing directly the request body:

app/controllers/JavaPoster.java

package controllers;

import play.mvc.*;

import views.html.*;

import java.util.Map;

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

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

Or using a DynamicForm:

package controllers;

import play.mvc.*;

import views.html.*;

import play.data.DynamicForm;

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

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

Now the scala version, accessing the body:

app/controllers/ScalaPoster.java

package controllers

import play.api.mvc._

object ScalaPoster extends Controller {

  def save = Action { request =>

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

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

}

And defining a form

package controllers

import play.api.mvc._

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

object ScalaPoster extends Controller {

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

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

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

}

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

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

You can also play with the tuples and issue something like

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

or

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

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

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

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

Troubleshooting Play Framework 2 apps on Openshift

Troubleshooting Openshift

With the do-it-yourself application type you really get a lot of freedom to support almost any framework or server that can be built and run on a linux box. But you do have to make your homework, and do some research.

So in this article I’ll show you a couple of tips I learnt playing around with Openshift and Play Framework.

Comments are more than welcome, so I hope you can also provide me some more tips to help us all get our apps running on the cloud.

Providing native support for play framework application

Right now, the solution we found for deploying Play 2.0 apps on openshift is quite handy, but we could make it a little better..

The problem is that we have to compile the app locally (issuing play stage) and then push 30 MB of libraries to Openshift. The ideal thing, and that’s what we did with the Play 1.x quickstart and with the latest version of Openshift module for Play Framework 1.x, would be to just upload our sources and then let Openshift download and install Play, compile our app, and start it.

Unfortunately we’ve ran with some memory constraints (seems like compiling Play 2 apps is a bit memory demanding) that eventually raised some issues. We are trying to work them out, but perhaps, with this tips, you could help has troubleshoot it.

With the opensourcing of Openshift and the new Origin livecd we have more tools available for us to further investigate what’s going on, I just didn’t have time yet to start playing with it.

So, enought chatter, and let’s get our hands dirty.

Houston, we have a problem

All right, you’ve just read this guide or followed our steps on the Play Framework webinar using this Play 2.0 quickstart (in fact, some of this tips will help trouble shoot any app running on Openshift) and something went wrong.

First of all, have a look at the logs. Just issue

rhc app tail -a myapp -l mylogin@openshift.com -p mysecretpass

Leave that window open, it will become quite handy later.

Then we’ll ssh into our remote machine. Just issue:

rhc app show -a myapp -l mylogin@openshift.com -p mysecretpass

and you’ll get something like

Application Info
================
contacts
    Framework: diy-0.1
     Creation: 2012-04-19T14:20:16-04:00
         UUID: 0b542570e41b42e5ac2a255c316871bc
      Git URL: ssh://0b542570e41b42e5ac2a255c316871bc@myapp-mylogin.rhcloud.com/~/git/myapp.git/
   Public URL: http://myapp-mylogin.rhcloud.com/

 Embedded: 
      None

Take the part after the ssh of the Git URL stuff, and log into you openshift machine:

ssh 96e487d1d4a042f8833efc696604f1e7@myapp-mylogin.rhcloud.com

(If you are lazy like me, go on and vote for an easier way to ssh into openshift)

It’s also a good idea to open another command window, ssh into openshift, and run something like “top” or “watch -n 2 free -m” to keep an eye on memory usage.

Troubleshooting Play

You know the old motto, “write once, run everywhere”… well it just “should” work, but just in case you could try compiling your app with the same JDK version as the one running on openshift.

Just run

java -version
java version "1.6.0_22"
OpenJDK Runtime Environment (IcedTea6 1.10.6) (rhel-1.43.1.10.6.el6_2-i386)
OpenJDK Server VM (build 20.0-b11, mixed mode)

And install the same jdk version on your box. Then compile your app and redeploy (you can use the convenience script openshift_deploy)

If that doesn’t work, try to do the whole process manually on Openshift. You should do something like this:

# download play
cd ${OPENSHIFT_DATA_DIR} 
curl -o play-2.0.1.zip http://download.playframework.org/releases/play-2.0.1.zip
unzip play-2.0.1.zip
cd ${OPENSHIFT_REPO_DIR}

#stop app
.openshift/action_hooks/stop

#clean everything - watch for errors, if it fails retry a couple more times
${OPENSHIFT_DATA_DIR}play-2.0.1/play clean 

if you get something like:

/var/lib/stickshift/0b542570e41b42e5ac2a255c316871bc/myapp/data/play-2.0.1/framework/build: line 11: 27439 Killed 

It means it failed miserably (that’s the memory problem I told you about)

And it’s such a bad tempered error that you’ll also loose you command prompt. Just blindily type “reset” and hit enter, you’ll get your prompt back.

And then just try again…

You might also get this message:

This project uses Play 2.0!
Update the Play sbt-plugin version to 2.0.1 (usually in project/plugins.sbt)

That means you created the app with Play 2.0 and you are now trying to compile it with a different version.

Just update project/plugins.sbt file or download the appropiate version.

Now compile and stage your app.

#compile everything - watch for errors, if it fails retry a couple more times
${OPENSHIFT_DATA_DIR}play-2.0.1/play compile

#stage - watch for errors, if it fails retry a couple more times
${OPENSHIFT_DATA_DIR}play-2.0.1/play stage

Then run it (don’t be shy and have a look at the action hooks scripts on the quickstart repo).

target/start -Dhttp.port=8080 -Dhttp.address=${OPENSHIFT_INTERNAL_IP} -Dconfig.resource=openshift.conf

Go check it at https://myapp-mylogin.rhcloud.com

If everything works ok, just stop it with ctrl-c, and then run:

.openshift/action_hooks/start

You should see your app starting in the console with the logs files

Now you can log out from the ssh session with ctrl-d, and issue:

rhc app restart -a myapp -l mylogin@openshift.com -p mysecretpass

and you should see something like

Stopping play application
Trying to kill proccess, attempt number 1
kill -SIGTERM 19128
/var/lib/stickshift/0b542570e41b42e5ac2a255c316871bc/openbafici/repo/target/start "-DapplyEvolutions.default=true" -Dhttp.port=8080 -Dhttp.address=127.11.189.129 -Dconfig.resource=openshift.conf
Play server process ID is 21226
[info] play - Application started (Prod)
[info] play - Listening for HTTP on port 8080...

I hope this tips will become useful. As I told, I’m looking forward to start playing with the Openshift Origin livecd, and then I’ll tell you about.

In the meantime I’ll leave you with the company of the good old Openshift Rocket Bear, I know you miss him too, so why not get him back?

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

Play framework en la nube de Red Hat

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

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

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

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

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

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

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

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

¡Esperamos que les guste!

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.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: