sábado, 10 de marzo de 2012

Silverlight front-end – Node.js back-end

He estado haciendo algunos experimentos con Node.js. Hay muchas cosas que ver sobre este tema en internet, desde servicios PaaS (Platform as a service) gratuitos como Nodester para colocar en la nube nuestras aplicaciones Node, interesantes frameworks para crear aplicaciones tipo MVC con Node.js como Express, motores de plantillas para la capa de presentación como Jade, y una plétora interminable de tecnologías interesantes construidas sobre Node.js para cubrir una gama muy amplia de soluciones a clásicos (y no tan clásicos) patrones de desarrollo.

Algo que no he encontrado hasta ahora en internet es algún mecanismo para hacer que una aplicación Silverlight utilice a Node.js en el back-end, así que me puse a probar algunos conceptos y en este post les comparto algunos de los resultados.

¿Porque usar esta peculiar combinación de tecnologías? Bueno, personalmente encuentro a Silverlight como la opción mas avanzada para crear aplicaciones RIA con gran enfoque en la usabilidad y con un enorme poder para desarrollar aplicaciones de línea de negocios (LOB). El pequeño detalle con Silverlight es que cuando toca a la puerta la necesidad de servir la aplicación desde un ambiente “Unixoide” quedamos fuera de combate. Si bien es cierto que existen tecnologías como Moonlight que permiten desarrollar aplicaciones con un clon de Silverlight para multiplataforma basado en Mono, hay muchos detalles que no están disponibles aun en Moonlight como por ejemplo el potente Entity Framework de Microsoft para desarrollar lógica compleja en una robusta capa de persistencia o bien las grandes ventajas de Visual Studio y el conjunto inagotable de infraestructuras .NET que facilitan enormemente el trabajo.

Entonces ¿que hacer si queremos tomar ventaja de las bondades de Silverlight en una aplicación RIA con interface de usuario sofisticada y a la vez necesitamos colgar toda la parte de servicios de datos en un eficaz servidor Linux usando una base de datos open source como Postgresql u otras y aprovechando tecnologías como Node.js?

En realidad no estoy totalmente seguro Risa

Pero de algo si estoy seguro… al hacer algunas pruebas he logrado establecer una mecánica para consumir datos vía servicios REST creado con Node.js desde una capa de cliente Silverlight.

El experimento consta de varias partes que explico a continuación:

Ingredientes
------------

  • Visual Studio 2010 con .NET Framework 4.5
  • Node.js y el módulo Express que usaremos para enrutar las peticiones hechas al servicio desde Silverlight
  • Opcionalmente se puede usar un módulo de acceso a datos para Node.js, por ejemplo pg para bases de datos Postgresql. Aunque este ejemplo lo mantendré simple y pondré datos manualmente construyéndolos en una estructura XML

Esta fuera del alcance de este articulo cualquier detalle de la instalación y uso de los módulos y herramientas señalados en los ingredientes. En los respectivos sitios web de cada cosa hay instrucciones y ejemplos suficientes.

Creando un pequeño servicio RESTful con Node.js

Con el siguiente código tendremos lo suficiente para exponer un servicio accesible a través del protocolo HTTP.

Contenido del archivo rest.js

   1:  var express = require('express');
   2:  var app = express.createServer();
   3:   
   4:  /*
   5:  Necesitamos que el servicio pueda exponer contenido estático 
   6:  para que silverlight pueda consumirlo usando clientaccesspolicy.xml
   7:  explicaciones aquí: 
   8:  http://msdn.microsoft.com/en-us/library/cc197955(v=vs.95).aspx
   9:  */
  10:  app.use("/", express.static(__dirname + '/'));
  11:   
  12:  var output = "";
  13:   
  14:  app.get('/rest', function(req, res) {
  15:   
  16:      output = "";
  17:      output += "<?xml version ='1.0' encoding='utf-8'?>";    
  18:      output += "<Users>";
  19:      output += "<User>";
  20:      output += "<Name>Pancho Villa</Name>";
  21:      output += "<Age>24</Age>";
  22:      output += "</User>";
  23:      output += "<User>";
  24:      output += "<Name>Spider Man</Name>";
  25:      output += "<Age>25</Age>";
  26:      output += "</User>";
  27:      output += "<User>";
  28:      output += "<Name>Edgar A. Poe</Name>";
  29:      output += "<Age>200</Age>";
  30:      output += "</User>";
  31:      output += "</Users>";
  32:   
  33:      res.send(output);
  34:  });
  35:   
  36:  app.listen(1337);



Este script es muy simple. Su tarea es definir la ruta de acceso a funciones javascript cuya respuesta arrojará un resultado en forma de XML vía HTTP. Si se utiliza un modulo de acceso a datos se puede fácilmente hacer que la respuesta se base en una consulta a una base de datos en vez de introducir la información manualmente.


La línea 10 del código establece una ruta ‘/’ que se refiere a la raíz del sistema de archivos donde se encontrará alojado el servicio. Esta ruta define un espacio donde se deberá colocar un archivo XML cuyo nombre debe ser exactamente clientaccesspolicy.xml que tiene por objetivo permitir a Silverlight confiar en el contenido del servicio. Esto se explica aquí.


El contenido del archivo clientaccesspolicy.xml es el siguiente para este ejemplo:


<?xml version="1.0" encoding="utf-8"?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from http-request-headers="*" http-methods="GET">        
        <domain uri="*" />
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true"/>
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>



En el caso de este ejercicio el archivo clientaccesspolicy.xml debe existir forzosamente en la ruta señalada ‘/’ es decir, exactamente en la misma ubicación (directorio raíz de nuestro servicio) que el archivo rest.js que contiene el script de Node.js.


Para ejecutar el servicio utilizamos el siguiente comando (dentro del folder donde se hayan colocados los archivos clientaccesspolicy.xml y rest.js):


(ya sea en *nix)
$node rest.js


(o bien en Windows)
>node rest.js


Lo anterior ejecuta el script de Node.js que estará escuchando en el puerto 1337 según nuestro ejemplo.


Esto es todo lo que necesitamos con respecto al lado del servidor.


 


Creando el cliente Silverlight para consumir el servicio


Ahora necesitamos un cliente que despliegue la información generada en el servicio que acabamos de crear.


Desde Visual Studio creamos una nueva aplicación Silverlight. Para este ejemplo agrego un DataGrid como se muestra en el siguiente código:


...
 
        <Grid x:Name="LayoutRoot" Background="White">
        <StackPanel Orientation="Vertical">
            <Border Background="#FF7BAED1" 
                    BorderThickness="2" 
                    BorderBrush="#FF0A0A0A">
                <TextBlock Text="Consumir REST con Silverlight" 
                           FontSize="12" 
                           FontWeight="Bold"></TextBlock>
            </Border>
 
            <sdk:DataGrid AutoGenerateColumns="True" 
                          Name="dataGrid1" 
                          HorizontalAlignment="Stretch" 
                          Height="150" 
                          VerticalAlignment="Stretch" 
                          UseLayoutRounding="True" 
                          Margin="10,100,10,0">
                
            </sdk:DataGrid>
        </StackPanel>                   
 
    </Grid>
...



Después de esto habrá que añadir una referencia al namespace System.Xml.Linq e incluir en las clausulas using del code behind (C# en este caso) la referencia:


using System.Xml.Linq;


Para este ejercicio vamos a usar Linq to XML para manejar algunos detalles de la conversión de los datos obtenidos a través de Http pero también es posible usar técnicas de serialización-deserialización que no veremos aquí.


El siguiente es el código (code behind) en C# se omiten partes no relevantes para fines de aprovechar mejor el espacio:




Creamos una clase dentro del code behind que concuerde con la estructura de los nodos especificados en el XML que se genera dentro del servicio en el archivo rest.js.


public class User
{
    [XmlElement]    
    public string Name { get; set; }
 
    [XmlElement]
    public int Age { get; set; }
}



Es importante que el nombre de la clase sea el mismo que el nombre del nodo raíz de la estructura XML y que los nombres de las propiedades correspondan de igual forma a los nombres de los atributos del XML.


El siguiente código muestra como implementar el resto del cliente.




   1:  namespace SLREST
   2:  {
   3:      public partial class MainPage : UserControl
   4:      {
   5:          public MainPage()
   6:          {
   7:              InitializeComponent();
   8:              
   9:              Uri serviceUri = new Uri("http://127.0.0.1:1337/rest");            
  10:              WebClient cliente = new WebClient();
  11:              
  12:              cliente.OpenReadCompleted += new OpenReadCompletedEventHandler(cliente_OpenReadCompleted);
  13:              cliente.OpenReadAsync(serviceUri);
  14:   
  15:          }
  16:   
  17:          void downloader_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
  18:          {
  19:              if (e.Error == null)
  20:              {
  21:                  Stream responseStream = e.Result;
  22:                  XDocument oDoc = XDocument.Load(responseStream);
  23:                  var Data = from info in oDoc.Descendants("User")
  24:                             select new User
  25:                             {
  26:                                 Name = Convert.ToString(info.Element("Name").Value),
  27:                                 Age = Convert.ToInt32(info.Element("Age").Value)
  28:                             };
  29:                  dataGrid1.ItemsSource = Data;
  30:                  
  31:              }
  32:              else
  33:              {
  34:                  txtOutput.Text = e.Error.ToString();
  35:              }
  36:          }
  37:      }
  38:  }



En el método MainPage se instancia un cliente web (de tipo WebClient) que apunta directamente al servicio creado con Node.js. Para este ejemplo tanto el cliente Silverlight como el servicio rest.js viven en el mismo servidor local.


Después de inicializar esto, se procede a crear un evento que se ejecutara cuando, en forma asíncrona, el cliente web solicite la petición al servicio. Al ser una llamada asíncrona toda la acción recae sobre este evento en donde, finalmente, se crea un objeto de tipo XDocument que contendrá la respuesta a la invocación del servicio. Usando Linq obtenemos los datos XML  y usando un objeto del tipo User (clase que creamos al inicio del code behind) para luego asignarlos a la propiedad ItemSource del DataGrid que definimos anteriormente en el XAML.


el resultado final luce así:


ss-slrst


 


Con muy poco código obtenemos el despliegue de datos en un grid muy bueno con capacidades para mover las columnas y ordenamiento en base a columnas con un simple click.


Este es un ejemplo muy sencillo pero la finalidad es dar una idea y un punto de partida que nos pueda servir para incursionar mas tarde en soluciones mas elaboradas y completas.

miércoles, 22 de febrero de 2012

Node.js – Green Computing

Javascript, de lenguaje basura a el alma de la fiesta

En los últimos años se ha visto un crecimiento meteórico en la adopción de nuevas tecnologías de programación basadas en javascript. Al principio quise ignorar ese lenguaje porque siempre lo había percibido como un lenguaje de scripting horrible y lo juzgaba como solo útil para la capa cliente de aplicaciones web, además de tener un nombre inadecuado, sintaxis tediosa y apestar a código espagueti. Después vi que estaba equivocado, o al menos en algunas de mis opiniones.

Primero note la enorme ventaja que daban los frameworks como jQuery y Dojo, luego todo el ruido relacionado con HTML5 y tecnologías para crear aplicaciones móviles. Entonces pensé “Mmm… este lenguaje que se veía tan de pacotilla si que va en serio”.nodejs-green

La cosa no para ahí y en el ultimo año se ha soltado una gran estridencia a causa de Node.js. Por si alguien no lo sabía ya,  Node.js es una tecnología que, por primera vez, nos permite usar javascript en el lado del servidor, una de las ventajas de esto es que se puede programar la capa cliente y la capa servidor con el mismo lenguaje javascript en forma transparente para cualquier plataforma.

Si eres un programador de la vieja escuela y sin conocimientos de javascript o programación basada en eventos y quieres conocer Node.js te enfrentaras a un cambio de paradigma bastante considerable pero que bien vale la pena afrontar dadas las condiciones bajo las que opera actualmente el mercado del desarrollo de software.

GreenComputinglogoGreen Computing y hacer mas con menos

Node.js es una tecnología de desarrollo totalmente orientada a eventos y programación asíncrona, construida sobre el motor V8 creado por Google para el navegador Chorme. Es una base para construir aplicaciones de red escalables y altamente eficientes. Al final del post verán links a recursos donde, con suerte, quedara mas claro todo esto.

La idea de Node.js es hacer mas con menos. El termino “green computing” se refiere precisamente a esto. Se trata de generar tecnología que consuma la menor cantidad posible de recursos (dinero, procesamiento, tiempo, memoria, almacenamiento, corriente eléctrica, líneas de código) y a su ves logre aportar la mayor cantidad posible de eficacia operativa a la vez sea mas amigable con el presupuesto e indirectamente incluso con el medio ambiente.

Con tecnologías como Node.js se consigue crear aplicaciones con un bajo consumo de RAM y mejor aprovechamiento del procesador (En ciertos tipos de tareas). Algunos detractores señalan que Node.js, al ser una arquitectura “single thread” o de un solo hilo, no logra aprovechar los beneficios de procesadores con múltiples núcleos lo cual es discutible ya que Node.js cuenta con mecanismos internos llamados “workers” que ofrecen la posibilidad de hacer un balanceo de trabajo distribuyendo la carga en mas de un núcleo. Confieso que actualmente ignoro como demonios funciona eso pero se habla mucho de que es un enfoque muy efectivo y revolucionario.

En un escenario ideal, con node.js se obtendría una plataforma que necesitará menos maquinas, presupuestos mas modestos, menor consumo de energía, ofreciendo resultados mas óptimos. Todo esto sin mencionar que con Node.js se usan muy pocas líneas de código en comparación con otras tecnologías “server-side”.

Habrá que esperar para ver como logra posicionarse Node.js en la industria. Algunos creen que es una tecnologia inovadora que llego para quedarse y que será revolucionaria y los detractores creen que es una moda que no tiene suficientes razones para existir y poco a poco ira desapareciendo. Solo el tiempo lo dirá pero creo que hay algunas pistas que sugieren un futuro promisorio para Node.js además de toda la alharaca generada en la prensa especializada: el apoyo de Microsoft patrocinando el desarrollo de Node.js e integrandolo en su plataforma Azure, Wallmart usando Node.js dentro de su infraestructura tecnológica y otros casos.

Personalmente he hecho muy pocos experimentos con Node.js pero tal vez escriba algunos reportes aquí sobre lo que vaya probando con esa nueva tecnología.

Links relacionados:

Sitio de Node.js
http://nodejs.org/

A Quick Introduction to How Node.js Works
http://cloud.dzone.com/articles/quick-introduction-how-nodejs

Fuerte critica a Node.js
http://teddziuba.com/2011/10/node-js-is-cancer.html

Node.js: Asynchronous I/O for Fun and Profit
http://www.infoq.com/presentations/Nodejs-Asynchronous-IO-for-Fun-and-Profit

Node.js Developer Guidance (Windows Azure)
http://msdn.microsoft.com/en-us/library/windowsazure/hh674489(v=vs.103).aspx