Précédent   Forum du club des développeurs et IT Pro > Java > Serveurs, conteneurs, et Java EE > Modularisation (OSGi, SCA...)
Modularisation (OSGi, SCA...) Forum d'entraide sur les architectures modulaires à base de composants et services (OSGi, SCA...). Avant de poster -> Les cours OSGi
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 25/02/2011, 15h34   #1
identifiant_bidon
Membre habitué
 
Inscription : juillet 2006
Messages : 690
Détails du profil
Informations forums :
Inscription : juillet 2006
Messages : 690
Points : 132
Points : 132
Par défaut [OSGi] Utilisation dans un bundle d'un service d'un autre bundle

Bonjour à tous

J'ai un sérieux pb. J'espère que qq'un pourra m'aider (George7 ? ) Comme dit dans le titre, j'utilise OSGI. Je dispose d'un workspace avec 2 projets (un projet Core et un projet plugin)

J'essaie de consommer un service du projet plugin dans mon projet Core mais

Code :
refs = context.getServiceReferences(SimpleShape.class.getName(), null);
me rend toujours null.

Voici mon code (Je simplifie au max. J'espère ne pas oublier de bout de code important) :
PROJET CORE

SimpleShape.java (une simple interface)
Code :
1
2
3
4
public interface SimpleShape
{
    public void draw();
}
Activator.java ( implements BundleActivator )

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
	public void start(final BundleContext context)
	{	
 
        ServiceTeamTILTTracker m_servicetracker = new ServiceTeamTILTTracker(context);
        m_servicetracker.open();
 
		ServiceReference[] refs;
		try {
			refs = context.getServiceReferences(SimpleShape.class.getName(), null);
			if (refs != null)
			{
				SimpleShape service = (SimpleShape) context.getService(refs[0]);
				service.draw();
 
				context.ungetService(refs[0]);
			}
			else
			{
				System.out.println("Couldn't find any dictionary service...");
			}
		} catch (InvalidSyntaxException e) {
			e.printStackTrace();
		}
	}

PROJET PLUGIN
Activator.java
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Activator implements BundleActivator
{
 
	public void start(BundleContext context)
    {
        Properties props = new Properties();
        context.registerService(SimpleShape.class.getName(), new Square(), props);
 
        System.out.println("Je suis dans mon module WS");
    }
 
    public void stop(BundleContext context)
    {
    }
 
    public class Square implements SimpleShape
    {
        public void draw()
        {
        	System.out.println("là, je suis en train de drawing");
        }
    }
}

Merci beaucoup. Je suis vraiment a court d'idées
__________________
https://www.weetool.com
identifiant_bidon est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/02/2011, 10h14   #2
George7
Membre Expert
 
Avatar de George7
 
Homme
Inscription : août 2006
Messages : 1 234
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 28
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : août 2006
Messages : 1 234
Points : 1 602
Points : 1 602
Salut,

(désolé du temps de réponse mais je rentre tout juste de vacances )
A priori ça me parait correct comme code... Ceci dit une première question : ton interface SimpleShape se trouve bien uniquement dans ton bundle core est est exportée par celui ci et importée par ton bundle plugin ?
Si ton bundle plugin contient aussi l'interface, cela ne peut pas marcher car chaque bundle ayant un classloader différent, les objets Class retournés pour enregistrer dans plugin et récupérer le serservice dans core sont différents.

Ensuite tu es sûr que ton plugin est démarré ? puis ton core ? Pour réaliser ce que tu veux il vaut mieux utiliser un ServiceTracker pour car si au moment du démarrage de core, aucun service SimpleShape n'est enregistré (plugin démarre après core, par exemple) il est normal que tu reçoives toujours null comme service.

Je vois que tu utilises un ServiceTracker mais que fait-il ?

je n'ai pas l'environnement sous la main pour montrer comment je ferais, mais si tu peux attendre ce soir ou demain je te montre volontiers

A plus
__________________
"Ikea / furnishing = OSGi / software : They allow to have very modular things, but trying to put them together generally drives you crazy"
-- Mario Fusco

Pour vos développements Java : apprenez à utiliser la javadoc
George7 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/02/2011, 16h36   #3
identifiant_bidon
Membre habitué
 
Inscription : juillet 2006
Messages : 690
Détails du profil
Informations forums :
Inscription : juillet 2006
Messages : 690
Points : 132
Points : 132
Salut George7 et merci pour ta réponse.

En ce qui concerne mon interface SimpleShape, elle se trouve bien uniquement dans mon bundle core et est bien exportée.

J'ai ensuite rajouté ce code dans le main de mon module core :

Code :
1
2
configMap.put("felix.auto.start.1", "file:plugin-1.0.0.jar");
configMap.put("felix.auto.start.2", "file:core-1.0.0.jar");
Enfin voici le code de mon ServiceTracker. Il n'y a pas grand chose dedans. J'ai l'impression que je devrai l'utiliser. Le hic, c'est que je ne sais pas trop quoi en faire :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
public class ServiceTrackerPerso extends ServiceTracker
{
    private static final int ADDED = 1;
    private static final int MODIFIED = 2;
    private static final int REMOVED = 3;
    private BundleContext m_context;
 
    public ServiceTrackerPerso (BundleContext context)
    {
        super(context, SimpleShape.class.getName(), null);
        m_context = context;
    }
 
    public Object addingService(ServiceReference ref)
    {
        SimpleShape shape = new DefaultShape(m_context, ref);
        processShapeOnEventThread(ADDED, ref, shape);
        return shape;
    }
 
    public void modifiedService(ServiceReference ref, Object svc)
    {
        processShapeOnEventThread(MODIFIED, ref, (SimpleShape) svc);
    }
 
    public void removedService(ServiceReference ref, Object svc)
    {
        processShapeOnEventThread(REMOVED, ref, (SimpleShape) svc);
        ((DefaultShape) svc).dispose();
    }
 
    private void processShapeOnEventThread(
        int action, ServiceReference ref, SimpleShape shape)
    {
        try
        {
            if (SwingUtilities.isEventDispatchThread())
            {
                processShape(action, ref, shape);
            }
            else
            {
                SwingUtilities.invokeAndWait(new ShapeRunnable(action, ref, shape));
            }
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }
 
    private void processShape(int action, ServiceReference ref, SimpleShape shape)
    {
        String name = (String) ref.getProperty(SimpleShape.NAME_PROPERTY);
 
        switch (action)
        {
            case MODIFIED:
                break;           	
            case ADDED:
                break;
            case REMOVED:
                break;
        }
    }
 
    private class ShapeRunnable implements Runnable
    {
        private int m_action;
        private ServiceReference m_ref;
        private SimpleShape m_shape;
 
        public ShapeRunnable(int action, ServiceReference ref, SimpleShape shape)
        {
            m_action = action;
            m_ref = ref;
            m_shape = shape;
        }
 
        public void run()
        {
            processShape(m_action, m_ref, m_shape);
        }
    }
__________________
https://www.weetool.com
identifiant_bidon est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/02/2011, 18h24   #4
George7
Membre Expert
 
Avatar de George7
 
Homme
Inscription : août 2006
Messages : 1 234
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 28
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : août 2006
Messages : 1 234
Points : 1 602
Points : 1 602
Pour en revenir au point précédemment abordé : nommer en dur les plugin dans le code est contre l'idée de la modularité OSGi
Sinon ce que je ferais :
dans mon bundle core lors du démarrage, je démarre un ServiceTracker perso qui traque les services de type SimpleShape
Ce que je ferais est dans dans mon Activator du bundle core
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 
public class Activator implements BundleActivator {
 
  private ServiceTracker tracker;
 
	public void start(BundleContext bundleContext) throws Exception {
		tracker = new MyTracker(bundleContext);
		tracker.open();
	}
 
	public void stop(BundleContext bundleContext) throws Exception {
	  tracker.close();
	}
 
	public class MyTracker extends ServiceTracker {
 
    public MyTracker(BundleContext context) {
      super(context, SimpleShape.class.getName(), null);
    }
 
    @Override
    public Object addingService(ServiceReference reference) {
      SimpleShape shape = (SimpleShape) context.getService(reference);
      shape.draw();
      return shape;
    }
	}
 
}
Ce qui veut dire que core va appeler la méthode draw de tout nouveau service de type SimpleShape enregsitré.
Ensuite peu importe l'ordre dans lequel les modules sont démarrés, dès que tu enregistreras un service de type SimpleShape, ton core appellera la méthode draw. Tu peux donc retirer les deux lignes moches avec les bundles en dur de ta configuration. J'ai testé chez moi et ça marche
__________________
"Ikea / furnishing = OSGi / software : They allow to have very modular things, but trying to put them together generally drives you crazy"
-- Mario Fusco

Pour vos développements Java : apprenez à utiliser la javadoc
George7 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/02/2011, 19h06   #5
identifiant_bidon
Membre habitué
 
Inscription : juillet 2006
Messages : 690
Détails du profil
Informations forums :
Inscription : juillet 2006
Messages : 690
Points : 132
Points : 132
Ok super merci George, je regarde ça demain, dès la première heure.

En fait, les lignes en dur, je l'ai avais mis juste pour faire des tests, ne t'inquiète pas. J'ai bien retenu ce que tu m'avais dit.
__________________
https://www.weetool.com
identifiant_bidon est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/02/2011, 19h18   #6
George7
Membre Expert
 
Avatar de George7
 
Homme
Inscription : août 2006
Messages : 1 234
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 28
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : août 2006
Messages : 1 234
Points : 1 602
Points : 1 602
Citation:
Envoyé par identifiant_bidon Voir le message
J'ai bien retenu ce que tu m'avais dit.
Attention interrogation écrite demain
__________________
"Ikea / furnishing = OSGi / software : They allow to have very modular things, but trying to put them together generally drives you crazy"
-- Mario Fusco

Pour vos développements Java : apprenez à utiliser la javadoc
George7 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/02/2011, 20h03   #7
pingoui
Membre habitué
 
Avatar de pingoui
 
Inscription : juillet 2004
Messages : 534
Détails du profil
Informations personnelles :
Âge : 32

Informations forums :
Inscription : juillet 2004
Messages : 534
Points : 129
Points : 129
Salut,

Quels sont les bundles que tu as lancer a part ton project.core et project.plugin ?

Pourquoi veux tu utiliser le serviceTracker pour une interface ?
La plupart du temps, on exporte le bundle contenant les interfaces et on importe celui-ci dans son bundle d'implementation.
Ensuite on publie l'implementation dans le registre.

Si tu utilise Equinox, je te conseille d'utiliser Declarative Service (plus souple) au lieu du serviceTracker.(lourd à mettre en place)

Ci-joint, un helloworld avec Equinox DS
Pour faire fonctionner Equinox, il faut "org.eclipse.osgi.jar"
et pour DS, il te faut "org.eclipse.equinox.ds.jar", "org.eclipse.osgi.services.jar" et "org.eclipse.equinox.util.jar"

Même si tu n'utilises pas Equinox, tu auras un petit exemple:
- d'import/export de bundle (myproject.service exporte ses interfaces / myproject.service.impl importe les interfaces)
- de publication/consommation de service.(myproject.service.impl publie ses services / myproject.helloworld consomme les services)

Et pour finir, un tutoriel qui explique parfaitement les béaba d'equinox


pingoui
pingoui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/03/2011, 14h08   #8
identifiant_bidon
Membre habitué
 
Inscription : juillet 2006
Messages : 690
Détails du profil
Informations forums :
Inscription : juillet 2006
Messages : 690
Points : 132
Points : 132
Super George7, merci encore une fois pour ta réponse.

Ceci dit, un derrier point :

Admettons en reprenant le code que tu as fourni, que la méthode draw (qui se trouve dans la méthode addingService de la classe MyTracker) renvoit un objet String.

Je voudrais récuperer ce String dans le start de mon Coer et en faire ce que je veux. Est-ce possible ?
J'espère que je suis assez clair.

pingoui : merci pour ta réponse mais j'utilise Felix

Merci
__________________
https://www.weetool.com
identifiant_bidon est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/03/2011, 16h02   #9
George7
Membre Expert
 
Avatar de George7
 
Homme
Inscription : août 2006
Messages : 1 234
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 28
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : août 2006
Messages : 1 234
Points : 1 602
Points : 1 602
Citation:
Envoyé par identifiant_bidon Voir le message
Super George7, merci encore une fois pour ta réponse.

Ceci dit, un derrier point :

Admettons en reprenant le code que tu as fourni, que la méthode draw (qui se trouve dans la méthode addingService de la classe MyTracker) renvoit un objet String.

Je voudrais récuperer ce String dans le start de mon Coer et en faire ce que je veux. Est-ce possible ?
J'espère que je suis assez clair.
Bon là ça devient plus embêtant
Sans rire, il faut juste déplacer ta logique dans ce cas là, elle est dans le ServiceTracker et pas dans la méthode start du core.
De toute façon une des recommandations en OSGi est d'avoir des méthodes start qui prennent le moins de temps possible, il ne faut pas mettre trop de logique. Imagine que tu as 100 bundles qui mettent chacun 100 ms à démarrer, tu as un temps de démarrage de 10 secondes déjà, les méthodes start sont appelées séquentiellement...

@pingoui: les Declarative Services font partie de la spécification OSGi, donc sont utilisables sur toute implémentation implémentant la partie compendium de la spec. Ceci dit ils servent surtout à enregistrer des services il me semble pas à écouter l'apparition de nouveaux services ou leur disparition.
Il me semble que le problème de identifiant_bidon est plus sur l'utilisation de services qui apparaissent que sur leur enregistrement
__________________
"Ikea / furnishing = OSGi / software : They allow to have very modular things, but trying to put them together generally drives you crazy"
-- Mario Fusco

Pour vos développements Java : apprenez à utiliser la javadoc
George7 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 03h41.


 
 
 
 
Partenaires

Hébergement Web