Compartir
Publicidad

Introducción a Play Framework 2 (Parte III: El Controlador)

Introducción a Play Framework 2 (Parte III: El Controlador)
Guardar
3 Comentarios
Publicidad
Publicidad

En esta serie introductoria a Play 2 Framework con Scala hemos hecho una muy breve introducción al lenguaje de programación Scala, además de descubrir como se crea el modelo de datos en una aplicación desarrollada con Play 2 Framework.

En esta nueva entrega vamos a descubrir como funciona el controlador. Como todos ya sabéis, Play 2 es un framework que sigue el patrón de diseño MVC ya que permite mantener sus diferentes componentes en orden y la lógica separada de la interfaz. Además, el patrón MVC está de moda en el desarrollo web desde hace ya varios años.

El Controlador

El controlador en Play 2 cumple con la misión de traducir consultas HTTP en algo entendible por el modelo de datos (que debe implementar la lógica de negocio de la aplicación). Un Controlador en Play 2 se compone de Actions y Results.

Actions

La mayoría de las peticiones recibidas por una aplicación desarrollada con Play 2 son manejadas por un Action. Un Action es básicamente una función que toma un objeto Request como parámetro y devuelve un objeto Result. Esta función maneja la petición proveniente del navegador y genera un resultado que es enviado al cliente. Por ejemplo:

def hello = Action { request =>
  Ok("Hello World!")
}

En el ejemplo anterior, Ok es un método que construye una respuesta 200 OK que contiene un cuerpo tipo text/plain. Existen muchos otros métodos que construyen respuestas "prefabricadas" a continuación el listado completo:

  • Accepted: Genera una respuesta 202 ACCEPTED
  • BadRequest: Genera una respuesta 400 BADREQUEST
  • Conflict: Genera una respuesta 409 CONFLICT
  • Created: Genera una respuesta 201 CREATED
  • EntityTooLarge: Genera una respuesta 413 REQUESTENTITYTOOLARGE
  • ExpectationFailed: Genera una respuesta 417 EXPECTATIONFAILED
  • Forbidden: Genera una respuesta 403 FORBIDDEN
  • Found: Genera una respuesta 302 FOUND
  • Gone: Genera una respuesta 410 GONE
  • InternalServerError: Genera una respuesta 500 INTERNALSERVERERROR
  • MethodNotAllowed: Genera una respuesta 405 METHODNOTALLOWED
  • MovedPermanently: Genera una respuesta 301 MOVEDPERMANENTLY
  • NoContent: Genera una respuesta 204 NOCONTENT
  • NonAuthoritativeInformation: Genera una respuesta 203 NONAUTHRITATIVEINFORMATION
  • NotAcceptable: 406 NOTACCEPTABLE
  • NotFound: General una respuesta 404 NOTFOUND
  • NotImplemented: Genera una respuesta 501 NOTIMPLEMENTED
  • NotModified: Genera una respuesta 304 NOTMODIFIED
  • PartialContent: Genera una respuesta 206 PARTIALCONTENT
  • PreconditionFailed: Genera una respuesta 412 PRECONDITIONFAILED
  • RequestTimeout: Genera una respuesta REQUESTTIMEOUT
  • ResetContent: Genera una respuesta 205 RESETCONTENT
  • SeeOther: Genera una respuesta 303 SEEOTHER
  • ServiceUnavailable: Genera una respuesta 503 SERVICEUNAVAILABLE
  • TemporaryRedirect: Genera una respuesta 307 TEMPORARYREDIRECT
  • TooManyRequest: Genera una respuesta 429 TOOMANYREQUEST
  • Unauthorized: Genera una respuesta 401 UNAUTHORIZED
  • UnsupportedMediaType: Genera una respuesta UNSUPPORTEDMEDIATYPE
  • UriTooLong: Genera una respuesta REQUESTURITOO_LONG

La idea detrás de todos estos métodos es que sean usados cuando sea necesario y se utilice el sistema de errores de HTTP de forma coherente. Por ejemplo podemos utilizar el método BadRequest de la siguiente forma:

def saluda = Action { implicit request =>
  saludoForm.bindFromRequest.fold(
    formWithErrors => BadRequest(html.createForm(formWithErrors)),
    saludo => Ok("Hola %s".format(saludo.name))
  )
}

También es posible generar respuestas "simples" (y flexibles) utilizando el método SimpleResult al que le pasamos como parámetros las cabeceras de la respuesta y el body, yo hago uso de este método para devolver JSON. Un ejemplo de uso sacado de la documentación de Play 2:

def index =Action{
  SimpleResult(
    header =ResponseHeader(200,Map(CONTENT_TYPE -> "text/plain")), 
    body =Enumerator("Hello world!")
  ) }

Por supuesto lo anterior es equivalente al primer ejemplo de este artículo. Además de esto podemos utilizar sencillas redirecciones con el método Redirect al que pasaremos como parámetro la ruta a donde reenviar al navegador y si lo queremos, un estado:

def index =Action{
  Redirect("/user/home", status = MOVED_PERMANENTLY) }

El Ejemplo

En el caso de nuestro ejemplo de aplicación, el controlador sería igual de sencillo que el resto del código que hemos escrito para él en los artículos anteriores:

package controllers
import play.api.data.Form
import play.api.data.Forms.{single, nonEmptyText}
import play.api.mvc.{Action, Controller}
import anorm.NotAssigned
import models.User
object Application extends Controller { val userForm = Form( single( "firstname" -> nonEmptyText, "lastname" -> nonEmptyText, "age" -> nonEmptyText ) def index = Action { Ok(views.html.index(userForm)) } def addUser() = Action { implicit request => userForm.bindFromRequest.fold( errors => BadRequest, { val person = Person(firstname, lastname, age) User.create(User(NotAssigned, person)) Redirect(routes.Application.index()) } ) } ) }

El objeto userForm mapea los parámetros de la petición a un objeto de tipo Form que puede aplicar validación a los datos introducidos. La función addUser maneja una petición e intenta mapear los parámetros de la petición al userForm. Si el proceso falla, se devuelve una respuesta tipo BadRequest, si no, se construye un nuevo objeto User que es guardado en la base de datos y se redirije el navegador al índice.

Nótese que al declarar request como implicit estamos haciéndolo accesible a otras APIs dentro del método addUser.

Esto es todo por hoy, en el siguiente artículo hablaremos sobre el enrutamiento.

Más en Genebeta Dev | Introducción a Play Framework 2

Temas
Publicidad
Comentarios cerrados
Publicidad
Publicidad

Ver más artículos