MicroServicios con Groovy

Si bien, existen muchas tecnologías muy completas que permiten la creación de servicios robustos, a veces me he visto en la necesidad de hacer algo pequeño. muy concreto pero mantenible, y que pueda soportar un volumen determinado. Es por esto que me he apoyado del poder que ofrece Groovy con ayuda de los Groovlets.

La parte que me gusta de este acercamiento es que el poder del Scripting se pasa al navegador, o en este caso, a un cliente que consume algún servicio web. Cuando usamos Groovlets tenemos disponible lo sisguiente:

  • request - HttpServletRequest
  • response - HttpServletResponse
  • application - ServletContext
  • session - HttpSession
  • out - PrintWriter
  • headers - Header[]
  • params - Un objeto tipo Map que contiene los parámetros

Ahora bien, que la configuración XML si es el caso es muy sencilla y sólo tenemos que agregar el Servlet de Groovy y hacer el mapeo.

<servlet>
  <servlet-name>Groovy</servlet-name>
  <servlet-class>groovy.servlet.GroovyServlet</servlet-class>
</servlet>

<servlet-mapping>
  <servlet-name>Groovy</servlet-name>
  <url-pattern>*.groovy</url-pattern>
  <url-pattern>*.gdo</url-pattern>
</servlet-mapping>

Nota: Que el mapeo no necesariamente es estricto con la extensión, podemos usar la que querramos.

Y aunque la implementación que muestro no sería la más adecuada, sirve de ejemplo para mostrar en pocas líneas la mayoría de los elementos antes mencionado:

Me apoyo de un par de clases que modelan un almacén de datos.

todos.groovy
class Todo {
  String description
}

@Singleton // Only one instance
class TodoManager {
  List<Todo> todos = []
}

Podemos jugar con el reponse directamente para decirle que cualquier respuesta sería JSON:

todos.groovy
response.contentType = 'application/json'
Buscar algún encabezado en particular para validar nuestra solicitud:

todos.groovy
def contentType = headers.find { k,v -> k.toLowerCase() == 'content-type' }?.value

if(contentType != "application/json"){
  response.status = HttpServletResponse.SC_BAD_REQUEST // We return a status code 400
  // Using the json method included
  json(status:"Please use 'application/json' header, just received ${headers} instead")
  return // And nothing more...
}

A partir de aquí podemos jugar con el método de envío y hacer algunas acciones, aquí una muestra muy simple:

todos.groovy
switch(request.method.toLowerCase()){ // Validating the method
  case 'get':
    json(todos:TodoManager.instance.todos) // Using the instance
  break
  case 'post':
    Todo todo = new Todo(description:params?.todo ?: "No description")
    TodoManager.instance.todos << todo
    response.status = HttpServletResponse.SC_CREATED
    json(todo:todo)
  break
  default:
    response.status = HttpServletResponse.SC_BAD_REQUEST
    json(status:"Method '${request.method.toLowerCase()}' not supported")
}

Puedes incluir estos tres últimos fragmentos en un archivo y todo funcionará sin problemas. Aunque, nuevamente no es la forma más adecuada, muestra muy bien el potencial del simple uso del Groovlet.

Al final podrías usar @Grab para obtener las dependencias de Jetty y levantar el contenedor en el mismo archivo.

Conclusión: En un par de líneas puedes conseguir un servicio pequeño, entendible y listo para pasarse a un proyecto de Gradle que permita estructurarlo mejor para irle creciendo.

comments powered by Disqus