Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Membre habitué
    Inscrit en
    juillet 2006
    Messages
    744
    Détails du profil
    Informations forums :
    Inscription : juillet 2006
    Messages : 744
    Points : 185
    Points
    185
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public interface SimpleShape
    {
        public void draw();
    }
    Activator.java ( implements BundleActivator )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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

  2. #2
    Invité
    Invité(e)
    Par défaut
    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

  3. #3
    Membre habitué
    Inscrit en
    juillet 2006
    Messages
    744
    Détails du profil
    Informations forums :
    Inscription : juillet 2006
    Messages : 744
    Points : 185
    Points
    185
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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);
            }
        }

  4. #4
    Invité
    Invité(e)
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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

  5. #5
    Membre habitué
    Inscrit en
    juillet 2006
    Messages
    744
    Détails du profil
    Informations forums :
    Inscription : juillet 2006
    Messages : 744
    Points : 185
    Points
    185
    Par défaut
    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.

  6. #6
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par identifiant_bidon Voir le message
    J'ai bien retenu ce que tu m'avais dit.
    Attention interrogation écrite demain

  7. #7
    Membre habitué Avatar de pingoui
    Homme Profil pro
    Activité professionnelle sans liens avec le developpement
    Inscrit en
    juillet 2004
    Messages
    562
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Activité professionnelle sans liens avec le developpement
    Secteur : Industrie

    Informations forums :
    Inscription : juillet 2004
    Messages : 562
    Points : 185
    Points
    185
    Par défaut
    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

  8. #8
    Membre habitué
    Inscrit en
    juillet 2006
    Messages
    744
    Détails du profil
    Informations forums :
    Inscription : juillet 2006
    Messages : 744
    Points : 185
    Points
    185
    Par défaut
    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

  9. #9
    Invité
    Invité(e)
    Par défaut
    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

Discussions similaires

  1. Réponses: 0
    Dernier message: 27/05/2014, 14h45
  2. Evolution service web et utilisation dans application web.
    Par REMACC1 dans le forum Services Web
    Réponses: 6
    Dernier message: 29/09/2009, 16h51
  3. Récupérer variables d'1 <form> et les utiliser dans X
    Par honeyz dans le forum XSL/XSLT/XPATH
    Réponses: 3
    Dernier message: 20/04/2006, 11h39
  4. caractère générique utilisable dans strcmp
    Par barthelv dans le forum C
    Réponses: 9
    Dernier message: 01/08/2003, 16h54
  5. Réponses: 7
    Dernier message: 26/06/2003, 09h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo