1

Bundle-A binds a package from Bundle-B using declarative services in Eclipse Environment.

Then Bundle-A sends a message to Bundle-B by passing a 'data' and 'a reference of a class object' that should get the response to this message as an argument. Eg. send(data, EgClass_1.this);

Bundle-B should process the message and send the response back to the class in Bundle-A that is awaiting response.

Unfortunately that is not possible in OSGi as it creates a cycle. Two bundles cannot import each other.

I wanted to pass reference to a class object so that Bundle-B can call a method on it to get information rather than passing too many arguments but most importantly so that Bundle-B can keep track of which class instance it should call the callback on. I will have multiple instance of the class & its child classes.

As a work around I separated Bundle_A into two, the interfaces and the implementation classes. This way Bundle_A can bind Bundle_B and also Bundle_B can import the Interface definition of Bundle_A interface so that it can work with the object reference passed as parameter.

But the above approach does not feel clean and in coincide with OSGi principles. Is there a better approach for this kind of two way communication or am I doing it right? Thanks in advance!

Excite
  • 484
  • 1
  • 5
  • 19
  • What makes you think that two bundles cannot import from each other? Of course they can. However it just makes a nonsense of the modularity... if two modules depend directly upon each other in such a tight loop, then just make them into a single module. – Neil Bartlett Jun 23 '15 at 13:43
  • I said that because Eclipse is showing the cycle error by displaying a red exclamation mark on both projects whenever I make import amongst two bundles. – Excite Jun 23 '15 at 14:02
  • 1
    Then Eclipse is lying to you. In OSGi it's perfectly possible to have a cyclic dependency (though not a good idea, as I described). – Neil Bartlett Jun 24 '15 at 12:18

1 Answers1

2

If I understood correctly you want to send data using the send call and be called back when B finishes. Bundle A needs to know the service interface to make the send call. So you will always have a dependency A->B. So to avoid a loop I would also define the callback interface in B. Some class in A can then implement the callback interface and you send the object instance as second parameter. B then just needs to know the callback interface.

Christian Schneider
  • 19,420
  • 2
  • 39
  • 64
  • If I understood you correctly, that will be similar to the work around I mentioned at the end of the question except in this case the interface will be inside bundle B rather than a third bundle I put as being a division of bundle A in to two, being interfaces & implementations. To make it more clear the callback will be called on the object instance that is passed as a second parameter when bundle A calls 'send' on bundle B. So I assume you are also saying this class that is passed as parameter should implement the callback interface located in B, am I right? – Excite Jun 23 '15 at 16:03
  • Yes. It is quite similar. The problem with your solution though is that Bundle B would still have a connection to the interface of bundle A. So it is not a circular dependency but still not ideal. Especially if bundle B might also be serving requests for other bundles. You would not want it to know all these interfaces. – Christian Schneider Jun 24 '15 at 12:44