Explicando Promises de JavaScript con un ejemplo simple

Hace unos días tuve la oportunidad de ver, una vez más, explicado el concepto de promesas y de objetos asíncronos, cuyo objetivo es, entre otros, evitar el llamado “callback-hell” que surge cuando llamamos a una función asíncrona en JavaScript.

En nuestro código frontend, es bastante habitual encontrarnos con funciones con este aspecto:

function myFunction(arguments,onSuccess,onError){
//Do things...
}

myFunction({val: 12}, function(){
    //Do things on success
}, function(){
    //Do things on error
});

El problema surge cuando encadenamos varias llamadas asíncronas, y ya no somos capaces de saber en qué función estamos ní cómo hemos llegado allí, además que el código se hace más difícil de leer.

Las promises o promesas, son objetos que nos permiten mejorar la legibilidad de nuestro código y evitar tener que pasar el contenido de las funciones directamente como argumentos a nuestra llamada.

En este artículo veremos una implementación muy simple de una promesa, para ver cómo funciona realmente, y comprobar que la base es un objeto simple con ciertas propiedades.

Nuestra clase Promise

Veamos por encima qué tenemos en nuestra clase Promise:

function Promise(){

    var self = this;
    var thenCallback = null;

    self.then = function(callback){
        thenCallback = callback;
    };

    self.complete = function(args){
        if (thenCallback && typeof thenCallback === 'function'){
            thenCallback(args);
        }
    };
}

Esta clase define dos funciones, una función then, en la que especificamos la función a ejecutar al terminar la acción, y una función complete, que nos permite ejecutar la función que hayamos definido, pasandole los argumentos necesarios.

Veamos un ejemplo de uso:

function myFunction(){

    var p = new Promise();
    setTimeout(p.complete, 1000)
    return p;
}

var promise = myFunction()
promise.then(function(){
    console.log('done');
});

En este caso, por una parte simulamos una llamada asíncrona con la función setTimeout, y por otra parte devolvemos la promesa. En el código que llama a la función, nos suscribimos al resultado de esa promesa, y podemos separar la ejecución de la función del tratamiento del resultado de la misma.

Gestión de errores y encadenamiento de promesas

Además de ejecutar funciones cuando todo ha ido bien, hemos de ser capaces de ejecutar acciones cuando se ha producido un error.

Para ello solamente tenemos que extender nuestra clase, agregando dos funciones adicionales, una se suscriba al error, que llamaremos error, y otra que ejecute la acción de error, que llamaremos fail.

self.error = function(callback){
        failCallback = callback;
};

self.fail = function(args){
    if (failCallback && typeof failCallback === 'function'){
        failCallback(args);
    }
}

Por otra parte, mediante un pequeño cambio podemos encadenar resultados:

self.error = function(callback){
        failCallback = callback;
        return self;
};

Este encadenamiento nos permite tener interfaces más fluidas, de tal manera que por una parte nos suscribimos al resultado de una función, y por otra parte al posible error:

promise.then(function(args){
    console.log('foo has happened ' + args);
}).error(function(args){
    console.log('error has happened');
});

Funciones “always”

Además de código que se ejecute cuando todo ha ido bien, o cuando todo ha ido mal, es posible que necesitemos código que se ejecute siempre, independientemente del resultado, lo que sería equivalente a la directiva “finally” de una función de C#.

Para ello solamente necesitamos agregar un nuevo callback a nuestra lista, que se ejecutará en caso de éxito o de fallo.

Conclusiones

Como vemos, las promesas no son “magia” que tienen algunas bibliotecas de JavaScript. Simplemente es otra sintaxis, otra manera de recuperar el control tras volver de una función asíncrona.

Si echamos un vistazo a lo que se propone para ECMAScript 6, lo que en la práctica será la próxima versión de JavaScript, veremos que las ideas son muy similares a lo que hemos visto en este artículo, aunque más extendido y detallado.

Tienes el código completo de la promesa en este gist

Enlaces adicionales

Diferentes tipos de “Promises”

Gracias a Antón Molleda (@molant) por los enlaces!

Friday fun: A++, ++A o A+=1? Esa es la cuestión…

Cuando empezamos a programar, una de las cosas que suelen quedar bastante claras (o no) es la diferencia entre i++, ++i e i+=1, mientras que la primera lee y luego asigna, la segunda asigna y luego lee, y la tercera lee y asigna. Personalmente no estaba del todo convencido, así que decidí verlo por mí mismo utilizando el compilador de C#, y comprobar cual era el código IL generado. Las funciones utilizadas son muy simples, y el código se ha compilado en modo debug.

¿Por qué el modo debug? Porque el modo release hace una serie de optimizaciones que dan como resultado exactamente el mismo código IL para un comportamiento sencillo. Veamos la primera función, con su respectivo código IL:

void APlusPlus(int A) 
{
    int B = A++;
}

El código IL es el siguiente:

.method private hidebysig instance void  APlusPlus(int32 A) cil managed
{
  // Code size       9 (0x9)
  .maxstack  3
  .locals init ([0] int32 B)
  IL_0000:  nop
  IL_0001:  ldarg.1
  IL_0002:  dup
  IL_0003:  ldc.i4.1
  IL_0004:  add
  IL_0005:  starg.s    A
  IL_0007:  stloc.0
  IL_0008:  ret
} // end of method Sample::APlusPlus

En este caso el funcionamiento es el siguiente:

  • Se carga el valor de A en la pila
  • Se duplica el valor de A.
  • Se suma 1 al valor de A
  • Se almacena el nuevo valor de A.
  • Se almacena el antiguo valor de A en B (A = B + 1).

Veamos el segundo candidato, en este caso la suma se realiza antes de la lectura.

void PlusPlusA(int A) 
{
    int B = ++A;
}

El código IL se muestra a continuación:

.method private hidebysig instance void  PlusPlusA(int32 A) cil managed
{
  // Code size       9 (0x9)
  .maxstack  2
  .locals init ([0] int32 B)
  IL_0000:  nop
  IL_0001:  ldarg.1
  IL_0002:  ldc.i4.1
  IL_0003:  add
  IL_0004:  dup
  IL_0005:  starg.s    A
  IL_0007:  stloc.0
  IL_0008:  ret
} // end of method Sample::PlusPlusA

En este caso el funcionamiento es el siguiente:

  • Se carga el valor de A en la pila
  • Se suma 1 al valor de A
  • Se duplica el valor del elemento almacenado en la pila.
  • Se almacena el nuevo valor en A.
  • Se almacena el nuevo valor en B (A = B).

Finalmente, veremos qué pasa con la construcción A+=1;

void APlusOne(int A)
{
    int B = A += 1;
}

El código IL es el siguiente:

.method private hidebysig instance void  APlusOne(int32 A) cil managed
{
  // Code size       9 (0x9)
  .maxstack  2
  .locals init ([0] int32 B)
  IL_0000:  nop
  IL_0001:  ldarg.1
  IL_0002:  ldc.i4.1
  IL_0003:  add
  IL_0004:  dup
  IL_0005:  starg.s    A
  IL_0007:  stloc.0
  IL_0008:  ret
} // end of method Sample::APlusOne

Si comparamos con el código anterior veremos que el resultado es exactamente igual, sin ningún cambio.

Conclusiones

Estas pequeñas pruebas nos permiten ver cómo funciona internamente el código IL, así como comprobar cómo se manipulan los objetos en operaciones sencillas. Si ejecutamos estas mismas operaciones en modo release cambia por completo, ya que el compilador elimina código no utilizado, así como valores nop que se insertan para facilitar la depuración.

Más info de ildasm en MSDN

Vídeo y enlaces del hangout sobre programación funcional

El pasado 11 de marzo tuve la oportunidad de moderar hangout sobre algunas de las ventajas que nos aporta la programación funcional con experiencias en F#, Scala y Clojure con estos cracks

El vídeo del evento está disponible aquí:

Además, compartimos algunos enlaces sobre la diferentes herramientas, y he recopilado estos enlaces en la siguiente lista:

Haskell

F#

Scala

Clojure

La lista está disponible además en github , así que puedes contribuir y agregar tus propios enlaces mediante Pull Requests.

Nos vemos en el siguiente!

Las 5 maneras en las que hago pruebas con ASP.NET

Al desarrollar aplicaciones en ASP.NET, tener un buen conjunto de pruebas es la diferencia entre encontrarte un fallo en desarrollo o en producción, así de sencillo. Las pruebas no evitan todos los errores, pero al menos nos permite que los caminos críticos se mantengan estables. Veamos de qué manera podemos probar nuestras aplicaciones ASP.net

1. Pruebas Unitarias

En una prueba unitaria probamos habitualmente los métodos y el comportamiento de una clase, aunque, por supuesto, no es necesario probar TODOS los métodos (getters y setters, por ejemplo, a menos que tengamos algun tipo de lógica de validación dentro de los mismos).

En una prueba unitaria, además, es importante que mantengamos aislada la clase a probar, de tal manera que todos los servicios o clases externas puedan ser simulados mediante mocks o clases de test específicas. Para estos mocks podemos recurrir a librerías como Moq.

Backend

Personalmente he utilizado tanto MSTest, NUnit como XUnit, estando más familiarizado con el primero ya que lo uso a diario. En general cada framework tiene sus características que lo hacen más interesante, aunque todo se reduce a encontar aquel con el que más cómodos nos sintamos.

Frontend

Si nuestra página contiene lógica de lado de cliente (por ejemplo, si estamos diseñando una SPA con Angular, Knockout o React) se hace prácticamente imprescindible el uso de tests. Para ello podemos recurrir a frameworks como QUnit, Jasmine o Mocha, herramientas que nos permiten establecer unas condiciones para crear tests, así como proporcionarnos un entorno de ejecución para ejecutar las mismas.

Estas herramientas, además, se pueden integrar con Visual Studio y también con Team Foundation Server/Visual Studio Online mediante la extensión Chutzpah que podemos agregar a nuestra solución.

2. Pruebas de integración

En una prueba de integración probamos la interacción entre diferentes módulos de nuestra aplicación, y en este caso el objetivo es asegurarnos que ciertos caminos funcionan correctamente entre las diferentes capas de la misma. Una prueba de aceptación no tiene por qué cubrir todo el sistema, sino que puede cubrir tan solo una parte del mismo.

Un ejemplo podría ser comprobar que el valor que llega a un controlador, pasa por la capa que valida la lógica de negocio de ese valor y finalmente devuelve una respuesta correcta, simulando la inserción en la base de datos.

Mientras más fuertes sean nuestras pruebas de integración entre componentes del sistema, más facilidad tendremos para encontrar y corregir posibles errores de regresión que no hayamos encontrado en pruebas unitarias, ya que, habitualmente, es en la interacción en donde pueden surgir más problemas inesperados.

3. Pruebas de UI

Una de las cosas que más problemas nos puede dar es no saber si los caminos críticos de nuestra web están funcionando correctamente, y para ello, la única manera de poder asegurarnos al 100% es mediante una prueba que simule un usuario navegando por la página. Para este cometido podemos utilizar Selenium, que nos permite grabar el comportamiento de un usuario en nuestra página y posteriormente reproducirlo, así como escribir este comportamiento en C# y ejecutarlo como si de un test de integración se tratara.

4. Pruebas de carga

¿Qué pasa cuando la aplicación recibe 1000 usuarios de golpe? ¿Soportará un “efecto menéame?. Benditos problemas, pero problemas al fin y al cabo. Si estamos trabajando en una solución que tenga que soportar cierta carga (prensa, bancos, redes sociales…) las pruebas de carga deben formar parte de nuestro plan de pruebas, ya que nos permitirán estresar el sistema y poder descubrir otro tipo de errores. Una de las herramientas para realizar estas pruebas de carga es JMeter del proyecto Apache, que nos permite además personalizar la salida de estas pruebas y poder ver los resultados como listas o como gráficas.

5. Tests exploratorios

Este tipo de pruebas resulta bastante interesante y ya hemos hablado de ellas en alguna ocasión ya que mezclan intuición y experiencia adquirida, para intentar encontrar nuevos fallos, errores o escenarios que se escapen del uso habitual del sistema (los denominados también “Corner cases”).

La ventaja de estos tests es que nos aportan un mayor conocimiento sobre el sistema, aunque pueden resultar difíciles de realizar o incluso tediosos, aunque hemos de pensar que no estamos haciendo el trabajo de la máquina, sino intentando ir un poco más allá.

Conclusiones

Aunque los test exploratorios pueden caer fuera del ciclo habitual de test de una tarea, no es conveniente dejarlos fuera, ya que nos pueden aportar mucho conocimiento sobre una herramienta, sobre todo si tenemos que trabajar con código heredado.

Estas son solo cinco opciones que personalmente uso o he usado en mi día a día, existen más sabores y tipos de tests, aunque el objetivo de todos es el mismo, asegurar la fiabilidad del código que estamos poniendo en producción.

¿Y tú, qué pruebas haces? Déjame un comentario o hablemos en @rlbisbe

Hangout: Programación funcional #hablafuncional

Tengo el placer de invitarte a un nuevo hangout el próximo 11 de Marzo a las 20:00 (GMT+1) donde hablaremos de programación funcional tanto con F# como con otros lenguajes como Scala o Clojure, continuando la conversación de la pasada DotNetSpain Conference.

Esta vez, además, contamos con un panel de auténtico lujo, en el que repite (como no podía ser de otra manera) mi buen amigo Juan Quijano (@jc_quijano) como moderador, además de los siguientes invitados:

  • Alex Casquete (@acasquete): Coordinador del Meetup de F# en Barcelona.
  • Alfonso García (@alfonsogcnunez): Coordinador del Meetup de F# en Madrid.
  • Juanma Hernandez (@gulnor): Desarrollador de software con mucho interés en Clojure.
  • Javi Pacheco (@javielinux): Desarrollador Android y Scala en 47 Degrees.
  • Francisco Díaz (@francisco_dr): Desarrollador Android y Scala en 47 Degrees.
  • Juan Pedro Moreno (@juanpedromoreno): Desarrollador Senior Scala en 47 Degrees.
  • Juan M Gomez (@_jmgomez_): Desarrollador F#.

Durante un par de horas intentaremos responder a las siguientes preguntas (y todas las que tengas a través del hashtag #hablafuncional):

  • ¿Qué aporta (en general) la programación funcional?
  • ¿Cómo podríamos dar nuestros primeros pasos para pensar en funcional?
  • ¿Cuan sencillo resulta interoperar con otras plataformas, C# en el caso de F# y Java en el caso de Scala/Clojure?
  • ¿Qué requisitos adicionales tenemos para agregarlo a nuestro proyecto?

Inscríbete aquí: Programación Funcional con F# – Google Hangouts

Desde aquí un agradecimiento a todos por su interés en participar, a todos los que se han interesado vía Twitter, , en especial a Alex Campos por ponernos en contacto con los chicos de 47 Degrees para dar otra perspectiva a la programación funcional.

DotNetSpain Conference 2015, yo estuve allí!

El pasado viernes y sábado 27 y 28 de febrero tuve la suerte de asistir, de ponente y de espectador, al evento DotNetSpain Conference 2015, un evento centrado fundamentalmente en .NET, sus lenguajes (en especial C# y F#), sus herramientas, y sobre todo su ecosistema, que cubre desde aplicaciones para dispositivos IoT hasta aplicaciones en la nube, tanto en hosts Linux como Windows, pasando por Windows Phone, iPhone y Android a través de Xamarin.

Como asistente, he disfrutado muchísimo de todas las sesiones a las que he asistido. En algunas he descubierto muchas malas prácticas que, para mi sorpresa, empleo diariamente, en esta sesión titulada Code Smells de Ferando Escolar (@fernandoescolar). Una sesión muy extensa de la cual pude sacar algunas notas:

image

image

Fernando ha publicado las slides en slideshare, así que las enlazo desde aquí también: Slides

Además, de la mano de Alex Casquete (@acasquete) pude comprobar cómo la programación funcional te permite hacer código más simple, más legible y con menor posibilidad de fallos. Además tuve la ocasión de tomar algunas notas:
image

image

Escoger entre las más de 45 sesiones y otros tantos talleres prácticos en solo dos días era difícil. Así, pude ver además temas relacionados con escalabilidad en la nube, gadgets variados en sesiones relacionadas con IoT, o algunos tips & tricks sobre C# que ignoramos. Ha sido muy interesante y traigo mucho que estudiar de vuelta.

Además de las charlas hubo tiempo para networking, ya que pude ver representación de las comunidades técnicas de toda España, así como muchos estudiantes llenos de inquietudes y de ganas de aprender miembros del programa Microsoft Student Partners, al que tuve el orgullo de pertenecer mientras fui estudiante. Algunos de estos estudiantes participaron, además, como ponentes en sesiones y talleres.

Este evento ha sido muy especial para mí, ya que he tenido la enorme oportunidad de participar como ponente en dos charlas bastante diferenciadas:

Una visión multiplataforma con ASP.net vNext

B-3c5x0W8AEoSu4

Por una parte pude compartir escenario con el gran Eduard Tomás (@eiximenis) en una sesión en la que estuvimos hablando de cervezas y de las novedades de ASP.net vNext para entornos multiplataforma. Vimos, además de las novedades que trae Visual Studio para el soporte de Grunt y Bower, que desplegar una aplicación compilada en Mac OSX, utilizando Sublime como editor y el proyecto Omnisharp para aportar Intellisense, en un contenedor Docker (en linux) ya es posible con unas pocas líneas.

Slides y ejemplos

Los ejemplos del apartado de MacOSX, que incluyen además los ficheros de configuración de Docker para desplegar, están disponible en GitHub

Vídeo

Esta sesión fue grabada por GlobbTV, y está disponible en su web: http://www.globbtv.com/12/microsite/4762/dotnetspain2015–una-vision-multiplataforma-con-aspnet-vnext

Extendiendo Visual Studio Online a través de su API

B-3lOhkW0AACJsQ

En mi segunda sesión, justo después, estuve mostrando utilizando algunos ejemplos, cómo mediante las APIs de Visual Studio Online podemos leer de nuestro proyecto, escribir y actualizar información, ejecutar operaciones como la solicitud de builds, y además, interactuar de manera pasiva mediante el uso de service hooks, para responder a eventos ya creados.

Slides y ejemplos

Los ejemplos utilizados se encuentran disponibles en GitHub

Conclusiones

Este evento ha sido una gran oportunidad para reconectar con muchos compañeros de profesión, para ponerme al día con diversos temas y además para poder compartir algo de lo aprendido en mis sesiones. Desde aquí muchas gracias a todos los asistentes, a la organización por hacer posible el evento y al resto de los ponentes por compartir con nosotros su experiencia.

Autenticación con Visual Studio Online desde Java usando OAuth

El protocolo OAuth nos proporciona una manera muy fiable de autenticación, así como la posibilidad de interconectar sistemas sin tener que ceder nuestras credenciales a un tercero.

Visual Studio Online es uno de los proveedores que lo soporta, aunque con ciertas peculiaridades. En este artículo veremos cómo podemos utilizar OAuth con Java para conectarnos y autenticarnos, así las peculiaridades de VSO.

Cómo funciona OAuth2.0

Oauth se basa en dos conjuntos de clave, conocidos como key y secret, que el cliente (Aplicación A) proporciona al sistema al que se quiere conectar (Aplicación B). Veamos un ejemplo del ciclo de vida de una petición OAuth:

  1. El usuario desde Aplicación A solicita autenticar con Aplicación B
  2. Aplicación A redirige a la página de Aplicación B con la Api_Key, la url de retorno y otros parámetros como parte de la redirección.
  3. El usuario introduce sus credenciales y autoriza (o no) la cesión de datos desde la Aplicación B a la Aplicación A.
  4. La Aplicación B redirige de vuelta a la Aplicación A con la url de retorno especificada anteriormente con un código de autenticación.
  5. De lado de servidor, la Aplicación A le envía a la Aplicación B el código de autenticación, el secret, y otros parámetros.
  6. La Aplicación B devuelve un Token a la Aplicación A que identifica al usuario y que se puede empezar a utilizar para realizar peticiones.

Cliente Oauth

Vamos a crear un ejemplo de Aplicación A, es decir, un cliente OAuth. Para ello utilizaremos scribe, un componente OAuth para Java muy sencillo y muy fácil de extender para adaptar a nuestras necesidades:

OAuthService service = new ServiceBuilder()
                                  .provider(LinkedInApi.class)
                                  .apiKey(YOUR_API_KEY)
                                  .apiSecret(YOUR_API_SECRET)
                                  .build();

A partir de ese código podemos generar la URL de redirección o capturar el Token. Como Visual Studio Online no forma parte de los proveedores por defecto, crearemos nuestro propio proveedor:

@Override
public class VSOnlineApi extends DefaultApi20 {

    @Override
    public String getAccessTokenEndpoint() {
        return "https://app.vssps.visualstudio.com/oauth2/token";
    }

    @Override
    public String getAuthorizationUrl(OAuthConfig oac) {
        return String.format("https://app.vssps.visualstudio.com/oauth2/authorize?mkt=es&client_id=%s&response_type=Assertion&state=sample&scope=vso.profile&redirect_uri=%s", 
                oac.getApiKey(), oac.getCallback());
    }

    @Override
    public Verb getAccessTokenVerb() {
        return Verb.POST;
    }

    
    @Override
    public OAuthService createService(OAuthConfig config) {
        return new VSOOauthService(this, config);
    }

    @Override
    public AccessTokenExtractor getAccessTokenExtractor() {
        return new VSOTokenExtractor();
    }
}

Este proveedor consta de dos urls, la de token y la de autorización, el verbo que utilizaremos para solicitar el access token, y dos componentes, un servicio que crearemos a continuación y el extractor para procesar el código resultado de la autenticación. Con este proveedor podemos generar la URL para realizar la redirección:


 OAuthService service = new ServiceBuilder()
                           .provider(VSOnlineApi.class)
                           .apiKey("KEY")
                           .apiSecret("SECRET)
                           .callback("https://rlbisbe.dev:4567/callback")
                           .signatureType(SignatureType.QueryString)
                           .build();

Por otra parte, para poder hacer la llamada del lado de servidor y validar el token necesitaremos implementar el servicio VSOOauthService, ya que la implementación OAuth de Visual Studio Online tiene ciertas peculiaridades.

public class VSOOauthService extends OAuth20ServiceImpl {

    private final DefaultApi20 api;
    private final OAuthConfig config;
    
    public VSOOauthService(DefaultApi20 api, OAuthConfig config) {
        super(api, config);
        
        this.api = api;
        this.config = config;
    }
    
    @Override
    public Token getAccessToken(Token requestToken, Verifier verifier)
    {
      OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint());
      request.addBodyParameter(VSOConstants.CLIENT_ASSERTION_TYPE, "urn:ietf:params:oauth:client-assertion-type:jwt-bearer");
      request.addBodyParameter(VSOConstants.GRANT_TYPE, "urn:ietf:params:oauth:grant-type:jwt-bearer");
      request.addBodyParameter(VSOConstants.CLIENT_ASSERTION, config.getApiSecret());
      request.addBodyParameter(VSOConstants.ASSERTION, verifier.getValue());
      request.addBodyParameter(OAuthConstants.REDIRECT_URI, config.getCallback());
      request.addHeader("Content-type", "application/x-www-form-urlencoded");
      config.log(request.getCompleteUrl());
      Response response = request.send();
      return api.getAccessTokenExtractor().extract(response.getBody());
    }
}

Esta clase nos permite construir una petición POST (que hemos visto antes en que nos permitirá validar el código que hemos recibido desde Visual Studio Online utilizando el secret de nuestra aplicación y las claves específicas que nos solicita la aplicación, enviar la petición y convertir el resultado en un Token para futuras peticiones.

Creando la web para conectarnos al servicio

Una vez que tenemos el servicio creado para obtener el token, vamos a crear una pequeña página para poder hacer el proceso completo. Para ello utilizaremos spark, un proyecto inspirado en Sinatra que nos permite crear aplicaciones web de una manera rápida y sencilla:


        OAuthService service = new ServiceBuilder()
                           .provider(VSOnlineApi.class)
                           .apiKey("KEY")
                           .apiSecret("SECRET")
                           .callback("https://rlbisbe.dev:4567/callback")
                           .signatureType(SignatureType.QueryString)
                           .debugStream(System.out)
                           .debug()
                           .build();
        
        get("/auth", (req, res) -> {
            res.redirect(service.getAuthorizationUrl(EMPTY_TOKEN));
            return null;
        });
        
         get("/callback", (req, res) -> {

             String code = req.queryParams("code");
             Verifier verifier = new Verifier(code);
             Token token = service.getAccessToken(EMPTY_TOKEN, verifier);
             return token;
        });

Con el sódigo anterior podemos ver dos puntos de entrada, /auth, que realiza la redirección al servicio, y /callback, que recoge el resultado de la redirección, parsea el código del resultado, solicita el token utilizando el servicio que hemos creado anteriormente y muestra el token como resultado:

Token[CODIFICADOENHEXADECIMAL, ]

Consideraciones adicionales: SSL

Visual Studio Online requiere que la url de retorno esté bajo el protocolo SSL y no admite localhost, con lo cual para pruebas lo que podemos hacer es crear un certificado autofirmado utilizando la utilidad Keytool de Java:

keytool -genkey -keyalg RSA -alias selfsigned -keystore keystore.jks -storepass password -validity 360 -keysize 2048

Además deberemos importar dicha keytool dentro de nuestro proyecto para poder utilizar HTTPS:

        SparkBase.setSecure("C:\\Users\\Roberto\\Documents\\NetBeansProjects\\OauthClientTest\\keystore.jks", "password", null, null);

Finalmente, como no admite localhost, una solución puede ser utilizar el nombre DNS de nuestro ordenador de pruebas, o bien mediante el fichero hosts crear una entrada para 127.0.0.1, en mi caso rlbisbe.dev

Documentación