viernes, 2 de junio de 2017

NetBeans Lookup API

NetBeans Lookup API

Esta API tiene 2 distintos propositos/significados, ambos enfocadoes en desacoplar modulos
.- JDK 6 ServiceLoader Class. proveedores de servicios multiples cargados por la clase  "LookUp"
via interface compartida.
.- Context Sensitivity. objetos Netbeans, e.g., windows, tienen un "lookup", definiendo capacidades, las cuales cambian dinamicamente.

Ejemplo:
pequeño ejemplo de uso JDK 6 service load

Este no usa los netbeans modules, se creará una simple aplicación java
File -> New Project -> Java -> Java Application
esta definirá un servicio que será expuesta a traves de un ServiceInterface
Crearemos otra simple aplicación java, donde pondremos la primer aplicación java dentro del classpath de la segunda aplicación java. La segunda aplicación java definirá el ServiceProvider
el cual implementa la interface (ServiceInterface). Esto es posible por que la primera aplicación java esta en el classpath de la segunda aplicación java. La segunda aplicación java expondrá el ServiceProvider a través del mecanismo JDK 6 ServiceLoader Class, por medio del paquete java META-INF.services, lo que es lo mismo un folder META-INF y subfolder services. el cual contiene un archivo con el nombre calificado del ServiceInterface. (org.demo.services.ServiceInterface como esta definida en la primer aplicación java). Este archivo contiene los nombres calificados de los ServiceProviders definidos en la segunda aplicación java. (org.demo.ServiceProvider1, org.demo.ServiceProvider2).
  Posteriormente se crea una trecer aplicación java, que dependera de la primera y segunda aplicación (agregar a la librería), esta utilizará JDK ServiceLoader Class, para cargar los ServiceProviders a través de ServiceInterface. Esto es posible por que la segunda aplicación expone los servicios por medio del folder META-INF services.
  Adicionalmente y no necesario para la simplicidad de este ejemplo, se crea una cuarta aplicación java que duplica a la segunda aplicación java, que en este caso define un ServiceProviderB1.

La estructura de estas sencillas aplicaciones java se muestra en NetBeans en la siguiente figura


El diagrama UML



La ejecución de la tercera aplicación 3AppServiceDisplayer llamara metodos de las otras aplicaciones por medio de la interface, gracias a las dependecias que el JDK 6 class loader puede resolver.

run:
Service Called:returns ServiceProvider1 from 2AppDemoService which implements ServiceInterface from 1AppDemoService
Service Called:returns ServiceProvider2 from 2AppDemoService which implements ServiceInterface from 1AppDemoService
Service Called:returns ServiceProviderB1 from 4AppDemoService which implements ServiceInterface from 1AppDemoService
BUILD SUCCESSFUL (total time: 0 seconds)

El código en github
https://github.com/jalbertomr/simpleLookupAPI.git


Otra Forma de llegar al mismo objetivo es usar la plataforma de Netbeans Modules, los cuales se comunicarán entre ellos, así se ayuda a tener un código más organizado. Esto se logra
creando un projecto NetBeans Platform Applications

File -> New Project -> NetBeans Modules -> NetBeans Platform Applications
name: AppSimpleNetBeansModule

Se ajustan las librerias a incluir a lo básico:
Project Window -> click derecho en AppSimpleNetBeansModule -> Properties -> Libraries -> platform
  Se eligen solamente los paquetes básicos esto es bootstrap, Startup, Module System, File System, Utilities adicionalmente sugerirá netbeans resolver agregar más paquetes por dependencia a lo que asentiremos positivamente.
Se agrega un nuevo modulo a la aplicación creada:
AppSimpleNetBeansModule -> Modules -> click derecho -> add new...
 project name: ModuleAppSimple

Le agregamos una Module Installer
ModuleAppSimple -> new.. -> Module Installer

Al método restored() que se generó, simplemente  le agregamos un println("Hello world");



y ejecutamos la aplicación AppSimpleNetBeansModule

-------------------------------------------------------------------------------
Hello World!
INFO [org.netbeans.core.startup.NbEvents]: Turning on modules:
    org.openide.util.lookup [8.33.1 201609300101]
    org.openide.util [9.7.1 201609300101]
    org.openide.util.ui [9.6.1 201609300101]
    org.openide.modules [7.48.1 201609300101]
    org.openide.filesystems [9.10.1 201609300101]
    org.openide.filesystems.compat8 [9.9.1 201609300101]
    org.netbeans.libs.asm [5.3.1 201609300101]
    org.netbeans.demo [1.0 170926]
    org.netbeans.core.startup.base [1.62.1.1 1 201609300101]
    org.netbeans.bootstrap/1 [2.76.1 201609300101]
    org.netbeans.core.startup/1 [1.62.1.1 201609300101]
BUILD SUCCESSFUL (total time: 31 seconds)

Indica como módulos pueden comunicarse con otros en una forma desacoplada.

Realizando la misma tarea que se hizo en el ejemplo que utiliza JDK 6 Class loader, pero con la plataforma NetBeans Modules, tenemos una estructura como esta

Project Properties -> API Versioning -> Public packages se hacen publicos los paquetes para que tengan visibilidad por los módulos que los utilizarán, y en los módulos que los utilizarán o haran referencia a ellos, se los agregarán en su librería.



Ejecutando tenemos:
-------------------------------------------------------------------------------
Windows Restored...
Service Called: ServicePrivider1 from DemoServiceProviderB which implements ServiceInterface from DemoService
Service Called: ServiceProvider1 from DemoServiceProviderA which implements ServiceInterface from DemoService
Service Called: ServiceProvider2 from DemoServiceProviderA which implements ServiceInterface from DemoService
INFO [org.netbeans.core.startup.NbEvents]: Turning on modules:
    org.openide.util.lookup [8.33.1 201609300101]
    org.openide.util [9.7.1 201609300101]
    org.openide.util.ui [9.6.1 201609300101]
    org.openide.modules [7.48.1 201609300101]
    org.openide.filesystems [9.10.1 201609300101]
    org.openide.filesystems.compat8 [9.9.1 201609300101]
    org.netbeans.libs.asm [5.3.1 201609300101]
    org.netbeans.core.startup.base [1.62.1.1 1 201609300101]
    org.netbeans.bootstrap/1 [2.76.1 201609300101]
    org.netbeans.core.startup/1 [1.62.1.1 201609300101]
    org.demo.service [1.0 170610]
    org.demo.serviceProviderB [1.0 170610]
    org.demo.serviceProvider [1.0 170610]
    org.demo.consumer [1.0 170926]
BUILD SUCCESSFUL (total time: 26 seconds)

El LookupAPI puede hacer más, No solamente es un service loader, en primera instancia tiene un listener el cual detecta cuando hay un nuevo service provider cargado por el runtime container. Esto permite integrar un módulo dinámicamente a una aplicación en runtime.
en segundo lugar se puede implementar context sensitivity

No hay comentarios:

Publicar un comentario