0

I've just got my hands-on with OSGI technology and I've few basic queries. Here is what I've done:

Created a HelloWorld interface in a package called "com.mypackage.osgi.bundle.service". This interface exposes a method as : public String sayHello(String arg);

Created a HelloWorldImpl class in a package called "com.mypackage.osgi.bundle.service.impl". This class implements the HelloWorld interface and provides an implementaion for sayHello() method.

Created a HelloWorldActivator class in a package called "com.mypackage.osgi.bundle.activator". This class implements the BundleActivator interface and implements the start() and stop() methods of interface.

In the start() method, I'm registering this bundle as a service via "BundleContext". The code is as shown below:

public class HelloWorldActivator implements BundleActivator {

ServiceRegistration helloServiceRegistration;

public void start(BundleContext context) throws Exception {

    HelloWorld helloService = new HelloWorldImpl();
    helloServiceRegistration =context.registerService(HelloWorld.class.getName(), helloService, null);    System.out.println("Service registered");    }

public void stop(BundleContext context) throws Exception {

    helloServiceRegistration.unregister();    System.out.println("Service un-registered");
} }

I'm then packaging this project as an OSGI bundle using maven plugin and deploying it on an OSGI container (Equinox). In the instructions I've exposed the interface as export-package. I can see that my OSGI bundle has successfully got deployed as a service on the OSGI container (The bundle id says ACTIVE state and also I can see the "Service registered" output on osgi console).

Now my next step is to consume the above OSGI bundle as a service. I understand that in order to do this, I can use "ServiceReference".

Suppose I'm now creating a totally new java project (so there is no link in this project's workspace with the one created above) such that it will act as a consumer to the service created above.

My query is - Do I need to create a "copy" of HelloWorld interface in this new java project ? In other words, I need to have this interface as a "stub" in this new project's workspace ?

The reason I ask this is because, if I do not have a copy of "HelloWorld" interface in my new project's workspace, I'm going to have compilation errors at line 2 and 3 mentioned below.

public class ConsumerActivator implements BundleActivator {

ServiceReference helloServiceReference;

public void start(BundleContext context) throws Exception {

    helloServiceReference= context.getServiceReference(HelloWorld.class.getName()); //2
    HelloWorld helloService =(HelloWorld)context.getService(helloServiceReference); //3
    System.out.println(helloService.sayHello("Test user"));

}
public void stop(BundleContext context) throws Exception {

    context.ungetService(helloServiceReference);
} }

So, is it correct to say that the consumer bundle should have "stubs" of the service interfaces that it intends to use ?

Sorry if it sounds a very basic question but just need to clarify as I couldn't find any mention of it anywhere on the net. All the examples provided assume that both consumer and service are part of same code workspace.

Many thanks in advance to clarify.

Best Regards LB

lbvirgo
  • 354
  • 1
  • 5
  • 22

2 Answers2

3

No, just create a dependency between the two projects.

Also, you should really not use the low level OSGi APIs if you are just starting out with OSGi. This is liking trying to hack the Linux kernel before you've even learning how to write a shell script! Please start with Declarative Services... see the tutorial here: http://bndtools.org/tutorial.html

Neil Bartlett
  • 23,743
  • 4
  • 44
  • 77
  • Thanks Neil but probably I was not clear enough in what exactly my doubt is. The point I'm trying to raise is - Does the consumer need to know about the service provider's interface ? In other words, someone says that there is a service registered by name "com.mypackage.osgi.bundle.service.HelloWorld" in an OSGI environment and anyone can use it. Now, is the service consumer good enough to consume this service by just knowing the service's registered name OR it needs to have this service interface as a stub in its code workspace ? – lbvirgo Dec 12 '13 at 02:57
  • The service consumer needs to import the package containing the service interface, using the `Import-Package` manifest header. There should only be one definition of the interface, which will be used by both the provider and the consumer. – Neil Bartlett Dec 12 '13 at 07:21
  • Thanks again for responding. I agree that OSGI container needs to be instructed of service interface being imported in service consumer via . But my point is, you still need to have the interface code file in the consumer's code workspace else the lines //2 and //3 in my code snippet mentioned in original post will give compilation error. I agree that project dependencies can be created but just think from view that the consumer code is being created on a different machine where it is totally unaware of provider's code base. – lbvirgo Dec 12 '13 at 07:56
  • The consumer code does need to compile against the interface, yes. If the API, provider and consumer projects are in the same workspace then you can create a direct inter-project dependency. If not then you need a way to share the compiled API jar. For example you could use a repository for this. – Neil Bartlett Dec 12 '13 at 09:12
  • That answers my query. Thanks a lot ! – lbvirgo Dec 12 '13 at 09:26
  • Hi, just one another quick thing - I created the service provider and service consumer bundles and deployed them in my osgi container. However got a "servicereference" null exception because the consumer is getting activated before the provider. If I deploy the provider bundle first and then do a "hot deployment" of consumer bundle, the consumer bundle does not get deployed (probably an issue with the osgi container i m using, I use WSO2 carbon framework). How can I ensure that my consumer bundle gets deployed only after provider bundle is ACTIVE ? – lbvirgo Dec 12 '13 at 09:59
  • You should not try to do this. Creating a start-ordering dependency is one of the most common and harmful anti-patterns in OSGi. Instead you should use a higher level abstraction like Declarative Services so that you don't need to worry about it. Unfortunately the OSGi Wiki appears to be down at the moment but when it is back, please read http://wiki.osgi.org/wiki/Avoid_Start_Order_Dependencies – Neil Bartlett Dec 12 '13 at 10:14
  • Agreed. Before I try to figure out on using DS (its bit confusing from whatever I read until now !), can you suggest on how "ServiceTracker" can be used to handle this situation. I believe (pls correct me if I'm wrong) "ServiceTracker" can also assist in holding the consumer bundle from being in ACTIVE state until the service producer becomes ACTIVE. – lbvirgo Dec 12 '13 at 12:04
  • In fact, I just found an extremely well written article by YOU on use of ServiceTracker http://www.eclipsezone.com/eclipse/forums/t90796.html Just wondering if you have the article for option 3 i.e., for "Don't be there in the first place." ? – lbvirgo Dec 12 '13 at 12:21
  • Service tracker is still more complicated than DS, I again strongly urge you to get to grips with DS first. To answer your question: the tracker's addingService method will be called when the service becomes available, so that's when you know it's safe to call the service. The addingService method will also be called if the service *already* existed before you opened the tracker. – Neil Bartlett Dec 12 '13 at 14:33
1

No, it is a best practice to have a separate bundle containing the interface as part of an API bundle. So you can have the interface separate from the actual service provider. However, in your case this approach is way over the top and I would colocate the HelloWorld interface and its (service) implementation in the same bundle.

s106mo
  • 1,243
  • 2
  • 14
  • 20
  • Thanks for responding. I agree but my query is more based on the dependency. Lets assume that we have separate bundles for interface and implementation, but my doubt is - how does the service consumer need a copy of interface in its code workspace ? – lbvirgo Dec 12 '13 at 03:00