Odelia>Technologiesbeta

Définir une interface graphique Swing mobile pour un objet cajo distant

|

Poursuivant notre découverte du projet cajo, commencée dans l'article « Introduction au projet cajo avec Groovy », nous allons dans cet article, toujours grâce au langage dynamique Groovy, définir une interface graphique Swing pour l'objet serveur : le but est de permettre à tout client, s'exécutant dans sa propre JVM et se liant à l'objet serveur, d'obtenir, puis d'instancier cette interface graphique localement ; celle-ci étant susceptible d'invoquer les méthodes publiques de l'objet distant.
Cette interface graphique peut être vue comme une interface graphique d'administration de l'objet serveur, tout comme dans la technologie Jini, dans laquelle le client d'un service Jini peut en obtenir une interface graphique d'administration.

Le titre de cet article mentionne une interface graphique mobile : c'est que celle-ci est tout simplement délivrée par l'objet serveur lui-même (appelons-le Item par la suite), plus précisément par l'une de ses méthodes publiques, sous la forme d'une chaîne de caractères contenant un script Groovy.
Ce script Groovy définit l'interface graphique utilisateur qui pourra être construite côté client : l'objet du script est de construire une instance de la classe Swing JFrame, à l'aide du builder Groovy SwingBuilder.

Voyons cela au travers d'un exemple !
Comme pour le premier article, les exemples de code Groovy qui seront utilisés pourront être exécutés directement dans la console Groovy venant dans la distribution de Groovy (ici, la version 1.5.6).
Nul besoin de rappeler que, du fait de l'intégration étroite entre Groovy et Java, ce code pourra être exploité dans tout type d'applications Java et/ou Groovy.


Côté serveur : l'Item définit son interface d'administration

Le code du script de la partie serveur est pratiquement identique à celui du premier article sur le framework cajo, si ce n'est que nous définissons une classe Test différente : celle-ci définit une propriété, parameter, et la méthode publique getUserInterface renvoyant un script Groovy comme valeur de retour.

import gnu.cajo.utils.ItemServer
import gnu.cajo.invoke.Remote

class Test {   

    def parameter = 'Salut !'

    public String getUserInterface() {
'''
import java.awt.BorderLayout

gui {
    frame(title: '
cajo et SwingBuilder', size: [300,300]) {
        borderLayout()
        label(text: "Paramètre : ${item.getParameter()}", constraints: BorderLayout.NORTH)
        label(text: "bla bla bla...", constraints: BorderLayout.CENTER)
        button(text: '
Modifier',
            actionPerformed: {
                item.setParameter('
Salut ! ' + new Date())               
            },
            constraints: BorderLayout.SOUTH
        )
    }
}
'
''   
    }
}

Remote.config(null, 1198, null, 0)

ItemServer.bind(new Test(), "unNom")

println "Le server s'exécute sur $Remote.serverHost, et le port $Remote.serverPort..."

Dans notre exemple, le script Groovy renvoyé par la méthode getUserInterface doit obligatoirement commencer par gui {...}. En langage Groovy cela équivaut à l'appel d'une méthode nommée gui ; le contenu de celle-ci devrait comprendre les appels qu'il est possible d'utiliser avec le builder SwingBuilder.
Dans notre exemple volontairement simple, le script permettra d'instancier un objet JFrame contenant un texte et un bouton.
Le script contient également une référence, item, représentant l'Item, et dont on se sert pour invoquer les méthodes de l'objet distant.
La classe Test définissant la propriété parameter, nous avons en réalité deux méthodes publiques : getParameter et setParameter générées par Groovy. L'appel item.getParameter permet d'initialiser la valeur du contrôle de type label, tandis que, en réponse au click sur le bouton, nous avons l'appel item.setParameter permettant de fixer une nouvelle valeur à la propriété parameter.

En lançant l'exécution du script de la partie serveur, une instance de la classe Test se retrouve exposée sur la machine locale au travers d'un serveur TCP, sur le port 1198.

Côté client

Dans le code du script de la partie cliente, et par rapport au premier article sur le framwork cajo, nous avons inclus la définition d'une classe utilitaire, CajoItemUI, chargée de récupérer puis de construire l'interface graphique de l'Item (objet serveur), et enfin d'afficher la fenêtre principale de l'interface. Tout ceci se produit dans la méthode CajoItemUI.show :

import gnu.cajo.invoke.Remote
import groovy.swing.SwingBuilder

class CajoProxy {
    def item

    CajoProxy(url) {
        item = Remote.getItem(url)
    }

    def methodMissing(String name, args) {
        if (args.length == 1)
            args = args[0]
        item.invoke(name, args)
    }
}

class CajoItemUI {
    def proxy
   
    def swing = new SwingBuilder()
    def frame

    CajoItemUI(proxy) {
        this.proxy = proxy
    }

    private def buildUI = {
        it.delegate = swing
        it()
    }
   
    def show = {
        def binding = new Binding([gui: buildUI, item: proxy])
        def shell = new GroovyShell(binding)
       
        frame = shell.evaluate(proxy.getUserInterface())       
        frame.pack()
        frame.show()
    }
}

def serverHost = '...' // Nom de l'hôte (serveur)
def proxy = new CajoProxy("//${serverHost}:1198/unNom")

def itemUI = new CajoItemUI(proxy)
itemUI.show()

Dans la méthode CajoItemUI.show, le script de l'interface utilisateur est obtenue par un appel à proxy.getUserInterface, où proxy est une référence vers l'Item. Puis ce script est évalué grâce à un objet GroovyShell : la méthode GroovyShell.evaluate renvoie un objet Swing JFrame, que l'on peut alors afficher.
Pour rendre cette évaluation possible, nous devons indiquer comment traiter l'appel gui qui figure au début du script de l'interface utilisateur ; cela est fait dans l'objet Binding transmis au constructeur de la classe GroovyShell : nous lions la variable gui à la closure CajoItemUI.buildUI ; par ailleurs, l'objet Binding définit aussi la variable item comme ayant la valeur proxy.
La closure CajoItemUI.buildUI permet la construction de l'interface graphique à partir du script reçu, en déléguant les appels à une instance de la classe SwingBuilder.

Si vous lancer l'exécution du script serveur, vous pouvez exécuter le script client, également à partir d'une nouvelle instance de la console Groovy, sur la même machine ou bien sur une machine séparée : l'interface graphique exposée par le serveur apparaît alors (attention, il se peut que la fenêtre de l'interface graphique n'apparaisse pas en avant-plan). Et un click sur le bouton changera la valeur de la propriété parameter de l'Item.

balises dans Langages et systèmes

AJAX cajo Camel DSL Grails Groovy Java JBI prefuse RSS ServiceMix SOA