Node.js para desarrolladores de Java

E/S ligeras e impulsadas por eventos para sus aplicaciones web

Node.js desenreda la concurrencia al sustituir el enfoque estándar de hebras múltiples de la plataforma de Java con E/S de una sola hebra e impulsadas por eventos. En este artículo, Andrew Glover presenta Node.js y explica por qué su concurrencia impulsada por eventos ha despertado tanto interés, aún entre desarrolladores acérrimos de Java. Después le muestra cómo aprovechar la infraestructura Express de Node, Mongolian DeadBeef y MongoDB para compilar una aplicación web concurrente, escalable y persistente.

Andrew Glover, CTO, App47

Andrew GloverAndrew Glover es un desarrollador, autor, ponente y emprendedor apasionado por el desarrollo impulsado por el comportamiento, la Integración Continua y el desarrollo de software de Agile. Es el fundador de la infraestructura de Desarrollo Impulsado por el Comportamiento (BDD) easyb y es el co-autor de tres libros: Continuous Integration, Groovy in Action y Java Testing Patterns. Puede estar al tanto de su trabajo en su blog y siguiéndolo en Twitter.



16-04-2012

JavaScript durante los últimos años ha surgido como un héroe del desarrollo de aplicaciones web. Este reconocimiento frecuentemente ha tomado por sorpresa a desarrolladores de software acostumbrados a descargar a JavaScript como un "lenguaje de juguete". Aunque hay lenguajes más populares (en el sentido del clamor de los desarrolladores para anunciar su lealtad hacia ellos), el estado exclusivo de JavaScript como el lenguaje de scripts estándar y neutral para los navegadores le ha otorgado un poder permanente. Para el desarrollo web del lado del cliente, posiblemente es el lenguaje más utilizado en el mundo.

JavaScript para desarrolladores de Java

JavaScript es una herramienta importante para el desarrollador de Java moderno y no es difícil de entender. Siga adelante mientras Andrew Glover presenta la sintaxis que necesita para compilar aplicaciones web de primera clase, incluyendo variables, tipos, funciones y clases de JavaScript.

JavaScript también tiene un lugar en los scripts del lado del servidor, y ese nicho está creciendo. Aunque han habido intentos en JavaScript del lado de servidor en el pasado, parece que ninguno ha capturado tanta excitación como Node.js o Node.

Diseñado para ayudar a los desarrolladores a construir programas de red escalables, Node es un entorno de programación del lado del servidor que virtualmente ha reinventado JavaScript para toda una nueva generación de desarrolladores. Para muchos desarrolladores de Java, lo más importante de Node es su nuevo enfoque para la concurrencia de software. Aunque la plataforma de Java continúa evolucionando en su enfoque para la concurrencia (con mejoras bastante anticipadas en Java 7 y Java 8), el hecho es que Node satisface una necesidad y lo hace en la forma más ligera que muchos desarrolladores de Java han adoptado recientemente. Como los scripts del lado del cliente con JavaScript, los scripts del lado del servidor en el entorno de Node son tan buenos debido a que simplemente funcionan, y están trabajando en un área donde muchos desarrolladores de Java son actualmente desafiados.

En este artículo, le presento la revolución de scripts del lado del servidor que es Node. Comenzaremos con una visión general de la arquitectura de lo que hace que Node sea especial y después le mostraré cómo compilar rápidamente una aplicación web escalable que aproveche a MongoDB para la persistencia de datos. Verá de primera mano lo divertido que es Node y lo rápido que puede usarlo para ensamblar una aplicación web funcional.

Concurrencia impulsada por eventos de Node

Node es un entorno de E/S escalable e impulsado por eventos construido sobre el motor de JavaScript V8 de Google. Google V8 realmente compila el JavaScript en código nativo de máquina antes de la ejecución, lo que resulta en un rendimiento del tiempo de ejecución extremadamente rápido — algo que normalmente no está asociado con JavaScript. Como tal, Node le permite compilar rápidamente aplicaciones de red que son increíblemente rápidas y altamente concurrentes.

E/S impulsadas por eventos puede sonar como algo extraño para los oídos del desarrollador de Java, pero no es tan nuevo. En lugar del modelo de programación de hebras múltiples al que estamos acostumbrados en la plataforma de Java, el enfoque de Node para la concurrencia es de una sola hebra, con la ventaja adicional de un bucle de eventos. Esta construcción de Node permite el no-bloqueo de E/S asíncronas. En Node, las invocaciones que normalmente bloquearían, como esperar los resultados de consulta de la base de datos, no lo hacen. En lugar de esperar a que se completen actividades costosas de E/S, una aplicación de Node emite una devolución de llamada. Cuando un recurso es retornado, la devolución de llamada adjunta es invocada en forma asíncrona.

¿Por qué elegir Node.js?

El enfoque de la plataforma de Java para la concurrencia ayudó a establecer su rol líder en el desarrollo empresarial, y no parece que eso vaya a cambiar. Infraestructuras como Netty (y Gretty; vea Recursos) y bibliotecas principales como NIO, así como java.util.concurrent, han hecho de la JVM la mejor opción para la concurrencia. Lo especial sobre Node es que es un entorno de desarrollo moderno específicamente diseñado para resolver los retos de la programación concurrente. El paradigma de la programación impulsada por eventos de Node significa que no necesita bibliotecas adicionales para hacer trabajo de concurrencia, y esas son buenas noticias para los desarrolladores interesados en el hardware multinúcleo.

La concurrencia simplemente funciona en programas de Nodo. Si quisiera ejecutar el escenario anterior en la plataforma de Java, haría mi selección de enfoques complejos y lentos — a partir de hebras tradicionales para bibliotecas más recientes en Java NIO e incluso el mejorado y actualizado paquete java.util.concurrent . Aunque la concurrencia de Java es poderosa, ¡puede ser difícil entender — lo que traduce el código! El mecanismo de devolución de llamada de Node, por comparación, está construido en el lenguaje; no necesita construcciones especiales como synchronized para hacerlo funcionar. El modelo de concurrencia de Node es extremadamente simple y eso lo hace accesible para una audiencia de desarrolladores más amplia.

La sintaxis de JavaScript de Node también le ahorra una enorme cantidad de pulsaciones del teclado. Con sólo un poco de código, usted puede compilar una aplicación web rápida y escalable que sea capaz de manejar numerosas conexiones concurrentes. También puede hacer eso en la plataforma de Java, pero necesitará más líneas de código y un grupo de bibliotecas y construcciones adicionales. Y si está preocupado por navegar un nuevo entorno de programación, no lo esté: Node es fácil de entender si conoce un poco de JavaScript, y apuesto a que así es.


Iniciándose con Node

Como he mencionado, es fácil iniciarse con Node, y encontrará un número de buenos tutoriales online para ayudarle con eso. En este artículo, como mi introducción del desarrollador de Java a JavaScript) Me estoy enfocando en ayudar a los desarrolladores de Java a aprovechar los beneficios de Node. En lugar de llevarlo a través de la aplicación de servidor web estándar "Hello, world", quiero entrar directamente a una aplicación significativa que realmente haga algo: piense en ella como un clon de tipo Foursquare construido en Node.

Video de demostración: iniciándose con Node.js

¿Prefiere un enfoque distinto para iniciarse con esta útil herramienta? Observe este video de demostración, también de Andrew Glover, para aprender más sobre Node.js y lo que puede hacer por usted. (Lea la transcripción.)

Instalar Node requiere que siga las instrucciones para su plataforma particular; si está usando una plataforma de tipo UNIX como OSX, recomiendo usar Node Version Manager, o NVM, que maneja los detalles de la instalación de una versión apropiada de Node. En cualquier caso, descargue e instale Node ahora.

También usaremos algunas bibliotecas de terceros para compilar esta aplicación, así que querrá instalar NPM, que es el gestor de paquetes de Node. NPM le permite especificar dependencias con versión de su proyecto, que después pueden ser descargadas e incluidas en su ruta de compilación. NPM es en muchas formas similar a Maven para la plataforma de Java, o al Bundler de Ruby.


Node Express

Node ha encontrado un buen hogar entre los desarrolladores web, para su capacidad de manejar la concurrencia y porque fue construido con el desarrollo web en mente. Una de las herramientas de Node de terceros más populares la infraestructura ligera de desarrollo web Express, la cual estaremos usando para desarrollar nuestra aplicación (vea Recursos para aprender más sobre Express).

Express está cargado con dispositivos, incluyendo enrutamiento sofisticado, vistas de plantilla dinámica (vea la infraestructura de Node du jour: Jade) y negociación de contenido. Express también es bastante ligero, sin ORM intercalado o un bagaje similar para aligerarlo. En esto, Express no es compatible con Rails, Grails o cualquier otra infraestructura web de pila completa.

Una forma sencilla de instalar y aprovechar Express es declararlo como una dependencia mediante un archivo package.json de NPM, mostrado en el Listado 1. Este archivo es similar a pom.xml de Maven o a Gemfile de Bundler, pero su formato es JSON.

Listado 1. Archivo package.json de NPM
{
  "name": "magnus-server",
  "version": "0.0.1",
  "dependencies": {
    "express": "2.4.6"
  }
}

En el Listado 1, le he dado a este proyecto de Node un nombre (magnus-server) y una versión (0.0.1). También he declarado la versión 2.4.6 de Express como una dependencia. Lo mejor de NPM es que recogerá todas las dependencias transitivas de Express, cargando rápidamente cualquier otra biblioteca de Nodo de terceros que requiera Express.

Después de que ha definido las dependencias de su proyecto mediante package.json, puede instalar los paquetes deseados mediante la línea de comandos al escribir npm install. Debe ver la instalación de NPM de Express junto con dependencias tales como connect, mime y más.

Escribiendo una aplicación de red

Comenzaremos escribiendo nuestra aplicación de ejemplo, Magnus Server, al crear un archivo de JavaScript; He nombrado el mío web.js, pero puede nombrarlo como usted guste. Abra ese archivo en su editor o IDE favorito; por ejemplo, puede usar JSDT, el plug-in de JavaScript de Eclipse (vea Recursos).

En este archivo, añada el código del Listado 2:

Listado 2. Magnus Server: First cut
var express = require('express');

var app = express.createServer(express.logger());

app.put('/', function(req, res) {
  res.contentType('json');
  res.send(JSON.stringify({ status: "success" }));
});

var port = process.env.PORT || 3000;

app.listen(port, function() {
  console.log("Listening on " + port);
});

Este pequeño fragmento de código hace grandes cosas, así que comenzaré por el principio. Primero, si deseo usar una biblioteca de terceros en Node, tengo que usar la frase require ; en el Listado 2, estamos requiriendo la infraestructura de Express y también obteniendo un manejador para ella mediante la variable express . Después, creamos una instancia de aplicación mediante la llamada createServer , que a su vez crea un servidor de HTTP.

Después definimos un punto final mediante app.put. En este caso, estamos definiendo un PUT de HTTP como el método requerido escuchando la raíz de la aplicación (/). La llamada put tiene dos parámetros: la ruta y una devolución de llamada correspondiente para ser ejecutada cuando esa ruta es invocada. El segundo parámetro es una función que es invocada durante el tiempo de ejecución cuando el punto final / es alcanzado. Recuerde que esta devolución de llamada es lo que Node quiere decir con impulsado por eventos o E/S con eventos — la devolución de llamada será invocada en forma asíncrona. Este punto final puede manejar numerosas solicitudes simultáneas sin la necesidad de crear manualmente las hebras.

Como parte de la definición de punto final, después creamos una lógica para manejar un PUT hasta /. Mantendremos las cosas simples por ahora al establecer el tipo de respuesta en JSON y después enviar de regreso un simple documento de JSON: ({"status":"success"}). Note el hábil método stringify , que toma un hash y lo convierte en JSON.

JavaScript y JSON

JSON y JavaScript son prácticamente hermanos, y esa afinidad se traduce en Node. Analizar JSON dentro de una aplicación de Node no requiere bibliotecas o construcciones especiales; en su lugar, usa llamadas lógicas que son similares a gráficos de objetos. En pocas palabras, Node trata a JSON como si fuera de la familia, lo que hace que la programación de aplicaciones web basadas en JSON sea mucho más fácil.

Después, creamos una variable representando el puerto en el que debe escuchar la aplicación; hacemos esto al obtener la variable de entorno PORT o estableciéndolo explícitamente en 3000. Finalmente, lanzamos la aplicación al llamar el método listen . Una vez más pasamos por una devolución de llamada, la cual será invocada una vez que la aplicación esté activa y en ejecución para imprimir un mensaje en la consola (en este caso, standard out).

¡Inténtelo!

Esta hábil aplicación responde a cualquier PUT, así que puede ejecutarla simplemente al escribir node web.js en la línea de comandos. Si desea probar más la aplicación, recomiendo descargar, de WizTools.org, RESTClient. Con RESTClient, puede saber rápidamente si Magnus Server funciona al ejecutar un PUT de HTTP para http://localhost:3000. Si todo sale bien, debe ver una respuesta de JSON indicando el éxito. (Vea Recursos para aprender más sobre la instalación y uso de RESTClient.)


Express lucha con JSON

JavaScript y JSON están estrechamente relacionados, lo que hace que gestionar JSON en Express sea lo más fácil posible. En esta sección, añadiremos un poco más de código al esqueleto de la aplicación en el Listado 2, de forma que podamos tomar un documento de JSON entrante e imprimirlo en standard out. Después de eso, persistiremos todo en una instancia de MongoDB.

El documento entrante se verá como algo parecido al Listado 3 (note que he omitido la información de ubicación para efectos de brevedad):

Listado 3. Free food at Freddie Fingers!
{
 "deal_description":"free food at Freddie Fingers",
 "all_tags":"free,burgers,fries"    
}

El Listado 4 añade funcionalidad para analizar el documento entrante:

Listado 4. Express analiza a JSON
app.use(express.bodyParser());

app.put('/', function(req, res) {
  var deal = req.body.deal_description;
  var tags = req.body.all_tags;

  console.log("deal is : "  + deal + " and tags are " + tags);
	
  res.contentType('json');
  res.send(JSON.stringify({ status: "success" }));
});

Note que el Listado 4 incluye una línea dirigiendo a Express para que use bodyParser. Esto nos permitirá tomar fácilmente (y en realidad quiero decir fácilmente) atributos de un documento de JSON entrante.

Dentro de la devolución de llamada put está el código para obtener los valores para los atributos deal_description y all_tags de un documento entrante. Note lo fácil que fue obtener los elementos individuales de un documento solicitado: en este caso, req.body.deal_description obtiene el valor de deal_description.

¡Pruébelo!

También puede probar esta implementación. Simplemente detenga su instancia de magnus-server y reiníciela, después use un PUT de HTTP para enviar un documento de JSON a su aplicación de Express. Primero, debe ver una respuesta exitosa. Después, Express debe registrar en standard out los valores que ha enviado. Con mi documento Freddie Fingers, obtengo la salida

deal is : free food at Freddie Fingers and tags are free, burgers, fries.

Persistencia con Node

Tenemos una aplicación funcional que recibe un documento de JSON, lo analiza y retorna una respuesta. Ahora necesitamos añadir algo de lógica de persistencia. Ya que soy un fanático de MongoDB (vea Recursos), yo elijo persistir los datos mediante una instancia de MongoDB. Para hacer las cosas aún más fáciles, aprovecharemos una biblioteca de terceros Mongolian DeadBeef, la cual usaremos para almacenar los valores de documentos de JSON entrantes.

Mongolian DeadBeef es una de las pocas bibliotecas de MongoDB disponibles para Node. La elijo porque su nombre me parece divertido y también porque su imitación del controlador nativo de MongoDB me hace sentir como en casa.

Ahora usted ya sabe que la primera etapa para usar Mongolian DeadBeef es actualizar el archivo package.json , como se muestra en el Listado 5:

Listado 5. Añadiendo análisis de JSON
{
  "name": "magnus-server",
  "version": "0.0.1",
  "dependencies": {
    "express": "2.4.6",
	"mongolian": "0.1.12"
  }
}

Ya que nos estamos uniendo con un almacén de datos de MongoDB, también necesitamos actualizar las dependencias duras del proyecto al ejecutar npm install. Para el rendimiento incrementado del controlador de MongoDB de Mongolian DeadBeef, también podemos instalar el analizador bson de C++, algo en lo que NPM nos puede guiar.

Para comenzar a usar Mongolian DeadBeef, añadimos otro require a la implementación actual, después nos conectamos a la instancia de MongoDB deseada (como se muestra en el Listado 6). Para este ejemplo, nos conectaremos a una instancia alojada en MongoHQ, un proveedor en la nube de MongoDB.

Listado 6. Añadiendo Mongolian DeadBeef a magnus-server
var mongolian = require("mongolian");
var db = new mongolian("mongo://a_username:a_password@flume.mongohq.com:23034/magnus");

Dentro de la devolución de llamada PUT , persistimos los valores del documento de JSON entrante, como muestra el Listado 7:

Listado 7. Añadiendo lógica de inserción de Mongolian
app.put('/', function(req, res) {
  var deal = req.body.deal_description;
  var tags = req.body.all_tags;

  db.collection("deals").insert({
     deal: deal,
     deal_tags: tags.split(",")
  })
	
  res.contentType('json');
  res.send(JSON.stringify({ status: "success" }));
});

Si observa de cerca, verá que la sentencia insert se ve idéntica a una inserción dentro del shell de MongoDB. Esta no es una coincidencia — ¡El shell de MongoDB usa JavaScript! Consecuentemente, podemos persistir con facilidad un documento que tenga dos campos: deal y deal_tags. Note cómo establecimos deal_tags en una matriz al usar el método split en la cadena de caracteres tags .

¿Puedo probarlo? (¡Si, sí puede!)

Si desea probar esto (¿y quién no querría hacerlo?), reinicie su instancia, envíela junto con otro documento de JSON y después proceda para verificar su colección deals dentro de MongoDB. Debe ver un documento de JSON casi idéntico al que envió.

Listado 8. Añadiendo lógica de inserción de Mongolian
{
  deal:"free food at Freddie Fingers",
  deal_tags: ["free", "burgers", "fries"],
  _id: "4e73ff3a41258b7423000001"
}

En conclusión, — ¡eso es todo!

Si piensa que sólo por flojo estoy finalizando tan pronto esta pequeña introducción a Node.js, entonces tengo noticias para usted: ¡hemos terminado! Sólo hemos escrito unas 20 líneas de código, pero se añaden a una aplicación persistente y en toda regla — y esa es la belleza de Node. Es increíblemente simple escribir y comprender, y las devoluciones de llamadas asíncronas lo hacen extremadamente poderoso. Una vez que una aplicación es escrita, puede ser desplegada en cualquier cantidad de proveedores de PaaS, para escalabilidad máxima.

Vea la sección Recursos para aprender más sobre las tecnologías discutidas en este artículo, incluyendo las opciones de Node.js, MongoDB y PaaS tales como Google App Engine, Elastic Beanstalk de Amazon y Heroku.

Recursos

Aprender

Obtener los productos y tecnologías

Comentar

  • Participe en la Comunidad My developerWorks: Conéctese con otros usuarios developerWorks mientras explora los blogs, foros, grupos y wikis orientados a desarrolladores.

Comentarios

developerWorks: Ingrese

Los campos obligatorios están marcados con un asterisco (*).


¿Necesita un IBM ID?
¿Olvidó su IBM ID?


¿Olvidó su Password?
Cambie su Password

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


La primera vez que inicie sesión en developerWorks, se creará un perfil para usted. La información en su propio perfil (nombre, país/región y nombre de la empresa) se muestra al público y acompañará a cualquier contenido que publique, a menos que opte por la opción de ocultar el nombre de su empresa. Puede actualizar su cuenta de IBM en cualquier momento.

Toda la información enviada es segura.

Elija su nombre para mostrar



La primera vez que inicia sesión en developerWorks se crea un perfil para usted, teniendo que elegir un nombre para mostrar en el mismo. Este nombre acompañará el contenido que usted publique en developerWorks.

Por favor elija un nombre de 3 - 31 caracteres. Su nombre de usuario debe ser único en la comunidad developerWorks y debe ser distinto a su dirección de email por motivos de privacidad.

Los campos obligatorios están marcados con un asterisco (*).

(Por favor elija un nombre de 3 - 31 caracteres.)

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


Toda la información enviada es segura.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=90
Zone=tecnologia Java
ArticleID=810020
ArticleTitle=Node.js para desarrolladores de Java
publish-date=04162012