Novedades en el proyecto Mylyn de Eclipse

El proyecto Mylyn de Eclipse, que viene instalado por defecto desde hace algunas versiones, convierte la interfaz de este IDE en una interfaz orientada a la tarea, integrándose con los sistemas de gestión de código (SCM) como Subversion o git y con los sistemas de control de bugs/tickets (como Bugzilla o Trac). Nosotros lo utilizamos habitualmente mediante una extensión que permite trabajar con Redmine.

Este proyecto es noticia, y merece una entrada en el blog, por dos razones. La primera es que ha sido promocionado como Top-level project dentro de Eclipse. Anteriormente, formaba parte del proyecto Tools. Lo más interesante de todo esto es que Mylyn (antes Mylar) fue el resultado de la tesis de Mik Kersten.

La segunda razón, viene de la mano de un proyecto de Google Summer of Code. Acaban de liberar una versión preliminar del conector Hudson para Mylyn. Por lo visto, Mylyn dispone de una API que permite conectar Mylyn a diferentes sistemas de integración continua simplemente desarrollando un conector para ellos.

Vista del Hudson de sidelab con el conector para Hudson de Mylyn

Ahora que Mylyn es un proyecto de primer nivel dentro de la estructura de Eclipse, tienen un montón de ideas para desarrollar y seguir innovando en el IDE. Y nosotros en Sidelab vamos a estar muy pendientes de esto…

SWT Browser: ¿el navegador definitivo?

No, no es el navegador definitivo, pero es muy versátil. El componente SWT Browser encapsula un navegador en un componente SWT que se puede utilizar en cualquier interfaz de usuario basada en SWT. Llegados a este punto, parece algo bastante útil. Permite mostrar páginas web en aplicaciones de escritorio, simplemente incluyendo el componente en la interfaz de la aplicación.

Pero SWT Browser es mucho más. En este post, Lars Voggel muestra cómo ejecutar código Javascript en un componente SWT Browser. También muestra cómo llamar a código Java de nuestra aplicación desde el código Javascript que ejecuta el navegador.

Cada vez es más frecuente que nuestra aplicación se integre con servicios que provienen de la web: Google Maps, redes sociales, etc. En este sentido, SWT Browser nos puede ayudar enormemente en esta tarea.

Cómo ejecutar trabajos en el UI thread

Cuando estoy desarrollando plug-ins, de vez en cuando me sucede que necesito hacer algo tan simple como mostrar un diálogo y suelo caer casi siempre en el mismo error. Supongamos el siguiente ejemplo:

MessageBox mb = new MessageBox(plugin.getWorkbench().getActiveWorkbenchWindow().getShell(), SWT.OK);
mb.setMessage(message);
mb.setText("Launching...");
mb.open();

Este código lo tengo en un plug-in que contribuye a la interfaz de usuario. Cuando lo ejecuto, obtengo NullPointerException. Al depurar, veo que getActiveWorkbenchWindow devuelve null. La documentación de este método especifica:

Returns null if called from a non-UI thread.

El problema es que no puedo ejecutar este método si no estoy en el UI thread. Si depuramos la ejecución podemos ver que no se está ejecutando en el hilo de despacho de eventos:

non-UI_thread

Para ejecutar código que necesita acceder a la UI (como mostrar un cuadro de diálogo) tenemos dos alternativas: Display.asyncExec(Runnable) y UIJob. La primera ejecuta un objeto Runnable en el hilo de eventos en cuanto tenga una oportunidad. No es bloqueante y no se avisa al que invoca asyncExec cuando la tarea termina.

UIJob es más versátil, permite utilizar prioridades para definir la prioridad de las diferentes tareas, permite avisar al que especificó la tarea (mediante UIJob.addJobChangeListeners) y se pueden especificar políticas de planificación en caso de que esta tarea no pueda ejecutarse concurrentemente con tareas en otros hilos.

La forma de utilizar UIJob es simplemente crear un objeto, implementar el método runInUIThread(IProgressMonitor) y finalmente invocar el método UIJob.schedule() para dejar la tarea encolada en el hilo de despacho de eventos:

UIJob uijob = new UIJob("Launching...") {
  @Override
  public IStatus runInUIThread(IProgressMonitor monitor) {
    MessageBox mb = new MessageBox(plugin.getWorkbench().getActiveWorkbenchWindow().getShell(), SWT.OK);
    mb.setMessage(message);
    mb.setText("Launching...");
    mb.open();
    return Status.OK_STATUS;
  }
};
uijob.schedule();

Ahora nuestra tarea se ejecuta en el hilo adecuado (Main es el hilo de despacho de eventos):

UI_thread