Posteado por: Willy Mejía | Julio 17, 2008

Gumbo: Flex 4 en gestación

La siguiente versión de Flex ya se está gastando en el sitio de Adobe Open Source bajo el nombre clave Gumbo, el cual se centrará en tres temas principales:

  • El Diseño “en mente”: Ofrecer un framework destinad a la colaboración continua entre diseñador y desarrollador
  • Productividad para el Desarrollador: Mejorar el rendimiento del compilador y agregar productividad a características del lenguaje como la vinculación de datos
  • Evolución del Framework: Aprovechamiento de las capacidades del nuevo Flash Player 10 y agregado de características requeridas por los casos de uso comunes

Para el primer punto el lenguaje MXML esta siendo ajustado para que herramientas como Thermo puedan generar aplicaciones Flex automáticamente. Además el nuevo formato FXJ, que permite describir gráficos de vectores en XML, simplificará el intercambio entre Thermo y Flex.

La primera Beta de Gumbo está planeada para finales del presente año, y la versión Final para mediados del siguiente.

Mas información en el sitio del proyecto: Gumbo.

Pero aparte de Gumbo Adobe también tiene otra iniciativa a largo plazo: crear una versión ligera del Flex framework para dispositivos móviles…

Posteado por: Willy Mejía | Julio 14, 2008

Java VisualVM

Sun ha publicado la séptima actualización del JDK 6, la cual incluye además la nueva herramienta Java VisualVM.

Java VisualVM es una nueva interfaz gráfica para la monitorización de, y la detección de problemas de rendimiento en aplicaciones Java. La misma incorpora herramientas de otros proyectos, como jstack, JMX, el Serviceability Agent (SA) y la herramienta de profiling de Netbeans, con el fin de proporcionar una herramienta visual de diagnóstico tanto para entornos de desarrollo como de producción.

Java VisualVM permite analizar cosas como el consumo de memoria, el CPU, thread dumps, head dumps, core dumps, etc. Pueden revisar la lista de las características en: visualvm features. Además, dado que está construida bajo la Plataforma de Netbeans, es extensible mediante plugins. Pueden verificar la lista actual de plugins en: visualvm plugins.

Mas información en el sitio del proyecto: visualvm.dev.java.net

Posteado por: Willy Mejía | Julio 14, 2008

Aplicaciones Compuestas con WPF

El equipo de patterns & practices de Microsoft ha publicado el conjunto de guías titulado: Composite Application Guidance for WPF. El cual contiene una implementación de referencia que emplea patrones de diseño, conceptos y técnicas para la construcción de aplicaciones compuestas con WCF. Incluye además ejemplos de inicio rápido, laboratorios, temas “como se hace”, etc.

La implementación de referencia ilustra cómo se pueden enfrentar muchos de los retos presentes en la construcción de aplicaciones basada en módulos independientes pero colaborativos.

Mas información en:

Posteado por: Willy Mejía | Julio 5, 2008

WCF bajo Contrato (4/4)

Contrato de Fallo

Cualquier operación petición/respuesta devuelve dos posibles mensajes: su mensaje de respuesta normal, o bien un mensaje de error. Para enviar un mensaje de error (un “SOAP Fault” en términos de servicios web) se lanza una FaultException en la implementación del servicio, tal y como se ha ejemplificado hasta ahora.

Pero además se pueden especificar formalmente los mensajes de error utilizando tipos personalizados con un contrato de datos adecuado, dado que se serializarán mediante el DataContractSerializer. El tipo a utilizar en el mensaje de error se especifica contractualmente en la firma de la operación utilizando el atributo FaultContract, mientras que en la implementación de la operación se genera mediante una FaultException del tipo especificado en el FaultContract.

Como ejemplo suponga que deseamos especificar un mensaje de error, que nos informe sobre un error en el parámetro de la petición, utilizando el siguiente tipo con su contrato de datos:

Listado de HelloData.cs (fragmento)

[DataContract(Namespace="http://hello/data/")]
public class InvalidRequest
{
  private int id;
  private string message;
  private string notes;

  [DataMember()]
  public int ID
  {
    get { return id; }
    set { id = value; }
  }

  [DataMember()]
  public string Message
  {
    get { return message; }
    set { message = value; }
  }				

  [DataMember()]
  public string Notes
  {
    get { return notes; }
    set { notes = value; }
  }
}

El fragmento de código se agrega al archivo HelloData.cs, tras lo cual lo compilamos.

Para especificar el uso del tipo InvalidRequest como tipo de fallo sobre la operación, aplicamos el atributo FaultContract a la firma de la operación:

Listado de Hello.cs (fragmento)

[ServiceContract(Namespace="http://hello/", Name="Hello")]
interface IHello
{
  [OperationContract()]
  [FaultContract(typeof(InvalidRequest))]
  SayHelloResponse SayHello(SayHelloRequest request);
}

Después en la clase de implementación del servicio se lanzan las excepciones correspondientes:

Listado de Hello.cs (fragmento)

  [ServiceBehavior(Namespace="http://hello/", Name="HelloService")]
  public class Hello : IHello
  {
    private StringBuilder message = new StringBuilder("¡Hola ");

    private void ValidateRequest(SayHelloRequest request)
    {
      if (request.PersonParameter == null)
      {
        InvalidRequest fault = new InvalidRequest();
        fault.ID = 1;
        fault.Message = "Parámetro Person inválido";
        fault.Notes = "El objeto Person no puede ser nulo...";
        throw new FaultException<InvalidRequest>(fault, "Parámetro inválido.");
      }
      else if (request.PersonParameter.FirstName == null ||
        request.PersonParameter.FirstName.Length == 0)
      {
        InvalidRequest fault = new InvalidRequest();
        fault.ID = 2;
        fault.Message = "Miembro FirstName inválido";
        fault.Notes = "El miembro FirstName del objeto Person no puede ser nulo o vacío...";
        throw new FaultException<InvalidRequest>(fault, "Parámetro inválido.");
      }
    }

    public SayHelloResponse SayHello(SayHelloRequest request)
    {
      ValidateRequest(request);

      message.Append(request.PersonParameter.FirstName + "!");
      string msg = message.ToString();
      SayHelloResponse response = new SayHelloResponse();
      HelloCard card = new HelloCard();
      card.Greeting = msg;
      response.HelloCardResult = card;
      System.Console.WriteLine(msg);
      return response;
    }
  }

Nótese que hemos extraído el código de validación del request en un método privado, en el cual se crea una instancia de InvalidRequest, se establece la información pertinente, y se lanza un FaultException con dicha instancia. Note además que se hace el uso de la versión “genérica” de FaultException para ello.

Compilamos Hello.cs, y para terminar del lado del servicio sólo ejecutamos la aplicación host.

Para el cliente una vez más se regeneran los artefactos cliente con svcutil.exe.

Después, aunque el código de la aplicación cliente podría funcionar sin cambios, para poder consumir los mensajes adicionales de error (de tipo InvalidRequest) ahora agregaremos un catch para “atrapar” el FaultException de tipo InvalidRequest. El listado de Client.cs queda de la siguiente manera:

Listado de Client.cs

using System;
using System.ServiceModel;

public class Client
{
  static void Main(string[] args)
  {
    String arg = null;
    String result = null;
    if (args.Length > 0) {
      arg = args[0];
    }
    else {
      arg = "Anónimo";
    }
    try {
      hello.Hello service = new hello.HelloClient();
      hello.data.Person person = new hello.data.Person();
      person.FirstName = arg;
      hello.SayHelloRequest request = new hello.SayHelloRequest();
      request.Person = person;
      hello.SayHelloResponse response = service.SayHello(request);
      result = response.HelloCard.Greeting;
    }
    catch (FaultException<hello.data.InvalidRequest> helloFault)
    {
      result = String.Format("{0}\nID: {1}\nMensaje: {2}\nNotas: {3}",
                helloFault.Message,
                helloFault.Detail.ID,
                helloFault.Detail.Message,
                helloFault.Detail.Notes);
    }
    catch (FaultException fault) {
      result = "Fault: " + fault.Message;
    }
    catch (Exception ex) {
      result = "Error: " + ex.ToString();
    }
    finally{
      System.Console.WriteLine(result);
    }
  }
}

Observe que para acceder a los miembros de la instancia de InvalidRequest enviada utilizamos la propiedad Detail de la instancia de FaultException helloFault.

Compilamos el proxy y el cliente, y ejecutamos Client.exe. Pruebe las excepciones modificando el código de la aplicación cliente, ya sea estableciendo a nulo el valor del miembro FirstName o el parámetro Person, y volviendo a compilar y ejecutar…

Epílogo

Con los ejemplos vistos en la presente serie se han explorado brevemente los diferentes tipos de contratos de WCF: contrato de servicio, contrato de datos, contrato de mensajes y contrato de fallo. Los mismos se definen aplicando ciertos atributos a clases y sus miembros. Los atributos permiten parámetros por nombre, tales como el Namespace y Name,  para una mejor definición del elemento al cual se aplica. Queda como tarea para el lector que indague sobre dichos parámetros, ya que existen muchos otros en cada uno de los distintos atributos.

Quedan pendientes entonces varias cosas, además del nuevo cliente Java, mismas que espero abordar en futuras ocasiones. ¡Hasta entonces!

Posteado por: Willy Mejía | Julio 4, 2008

WCF bajo Contrato (3/4)

Contrato de Mensajes

Hasta ahora se ha redefinido el contrato de servicio utilizando una interfaz, así como empleado tipos personalizados con contrato de datos definidos, lo cual es suficiente en la mayoría de los casos.

Pero cuando se desea tener mayor control sobre la estructura de los mensajes SOAP debemos crear un contrato de mensajes el cual permite utilizar un tipo para el parámetro y el valor devuelto que se serialicen en los mensajes SOAP de solicitud y respuesta que se necesiten.

A éste estilo de modelado de las operaciones se le conoce como estilo de mensajería, en contraposición al estilo de llamada de procedimiento remoto (RPC). Las firmas de las operaciones de estilo de mensajería tienen hasta un parámetro y un valor de retorno y ambos deben ser tipos de mensaje que se serializan directamente en una estructura del mensaje SOAP especificado.

Para definir el contrato de mensajes debemos aplicar el atributo MessageContract a las clases que vayan ser los tipos de mensaje. Así también debemos aplicar el atributo MessageBodyMember a sus miembros (que pueden ser campos, propiedades o eventos) que serán los elementos del cuerpo del mensaje SOAP, o bien el atributo MessageHeader para especificar el encabezado del mensaje.

Podriamos haber empleado el contrato de mensajes desde la versión del servicio que empleaba tipos simples, en cuyo caso podría ser algo como:

[MessageContract()]
public class SayHelloRequest
{
  [MessageBodyMember()]
  public string name
}

[MessageContract()]
public class SayHelloResponse
{
  [MessageBodyMember()]
  public string greeting
}

Pero continuando con nuestro ejemplo, los contratos de mensaje para la operación SayHello quedan de la siguiente forma:

Listado de Hello.cs (fragmento)

using hello.data;

  [MessageContract()]
  public class SayHelloRequest
  {
    private Person person;

    [MessageBodyMember(Name="Person")]
    public Person PersonParameter
    {
      get { return person; }
      set { person = value; }
    }
  }

  [MessageContract()]
  public class SayHelloResponse
  {
    private HelloCard helloCard;

    [MessageBodyMember(Name="HelloCard")]
    public HelloCard HelloCardResult
    {
      get { return helloCard; }
      set { helloCard = value; }
    }
  }

Nótese que se trata de clases “planas” con atributos, y que los elementos del cuerpo de los mensajes son los tipos personalizados con contratos de datos definidos anteriormente en HelloData.cs.

Para utilizar los tipos de mensaje ahora la firma del contrato de servicio debe redefinirse como sigue:

Listado de Hello.cs (fragmento)

[ServiceContract(Namespace="http://hello/", Name="Hello")]
interface IHello
{
  [OperationContract()]
  SayHelloResponse SayHello(SayHelloRequest request);
}

Por lo que también debemos reescribir su implementación. El listado completo de Hello.cs queda entonces de la siguiente forma:

Listado de Hello.cs

using System;
using System.Text;
using System.ServiceModel;
using hello.data;

namespace hello
{

  [MessageContract()]
  public class SayHelloRequest
  {
    private Person person;

    [MessageBodyMember(Name="Person")]
    public Person PersonParameter
    {
      get { return person; }
      set { person = value; }
    }
  }

  [MessageContract()]
  public class SayHelloResponse
  {
    private HelloCard helloCard;

    [MessageBodyMember(Name="HelloCard")]
    public HelloCard HelloCardResult
    {
      get { return helloCard; }
      set { helloCard = value; }
    }
  }

  [ServiceContract(Namespace="http://hello/", Name="Hello")]
  interface IHello
  {
    [OperationContract()]
    SayHelloResponse SayHello(SayHelloRequest request);
  }

  [ServiceBehavior(Namespace="http://hello/", Name="HelloService")]
  public class Hello : IHello
  {
    private StringBuilder message = new StringBuilder("¡Hola ");

    public SayHelloResponse SayHello(SayHelloRequest request)
    {
      if (request.PersonParameter == null ||
          request.PersonParameter.FirstName == null ||
          request.PersonParameter.FirstName.Length == 0)
        throw new FaultException(
            "Parámetro Person inválido.");

      message.Append(request.PersonParameter.FirstName + "!");
      string msg = message.ToString();
      SayHelloResponse response = new SayHelloResponse();
      HelloCard card = new HelloCard();
      card.Greeting = msg;
      response.HelloCardResult = card;
      System.Console.WriteLine(msg);
      return response;
    }
  }
}

Las clases de los archivos HelloData.cs y HelloHost.cs permanecen sin cambios. Por lo que del lado del servicio únicamente compilamos el archivo Hello.cs:

>csc /t:library Hello.cs /r:System.ServiceModel.dll,HelloData.dll

…y ejecutamos la aplicación host.

Continuemos con el cliente. Primero debemos (una vez más) regenerar los artefactos cliente con svcutil.exe, y después modificar el código de Client.cs como se muestra a continuación:

Listado de Client.cs

using System;

public class Client
{
  static void Main(string[] args)
  {
    String arg = null;
    String result = null;
    if (args.Length > 0) {
      arg = args[0];
    }
    else {
      arg = "Anónimo";
    }
    try {
      hello.Hello service = new hello.HelloClient();
      hello.data.Person person = new hello.data.Person();
      person.FirstName = arg;
      hello.SayHelloRequest request = new hello.SayHelloRequest();
      request.Person = person;
      hello.SayHelloResponse response = service.SayHello(request);
      result = response.HelloCard.Greeting;
    }
    catch (System.ServiceModel.FaultException fault)
    {
      result = "Fault: " + fault.Message;
    }
    catch (Exception ex) {
      result = ex.ToString();
    }
    finally{
      System.Console.WriteLine(result);
    }
  }
}

Nótese que antes del llamado al método SayHello se deben crear una instancia del tipo de mensaje SayHelloRequest, así como el tipo Person para su miembro correspondiente. La invocación retorna una instancia del tipo de mensaje SayHelloResponse mediante la cual se recupera el mensaje a desplegar. Note también que los elementos de los mensajes tienen los nombres especificados en el argumento por nombre “Name” del atributo MessageBodyMember correspondiente.

Para finalizar compilamos el proxy y la aplicación cliente, y ejecutamos Client.exe como hasta ahora.

Dado que en el presente ejemplo no hemos empleado el contrato de mensajes para nada extraordinario, el uso del mismo pareciera una sobrecarga innecesaria. Pero tenga presente que es útil para aquellos casos en los cuales se requiere tener control sobre los elementos o cabecera del mensaje, tales como la resolución de problemas de seguridad del mensaje o problemas de interoperabilidad.

Entradas antiguas »

Categorías