|
|
Line 5: |
Line 5: |
| # Check out the [https://guest:1673852@zenit.senecac.on.ca/svn/ecl500/Lectures/trunk/w11-osgi-simple-serviceconsumer/ Service Consumer] | | # Check out the [https://guest:1673852@zenit.senecac.on.ca/svn/ecl500/Lectures/trunk/w11-osgi-simple-serviceconsumer/ Service Consumer] |
| | | |
− | <h3>Steps for Building Bundels</h3> | + | <h3>[[Steps for Building Bundels]]</h3> |
− | | |
− | <h4>1. Study the Interfaces</h4>
| |
− | | |
− | * [http://www.osgi.org/javadoc/r4v42/org/osgi/framework/Bundle.html Bundle]
| |
− | * [http://www.osgi.org/javadoc/r4v42/org/osgi/framework/BundleContext.html BundleContext]
| |
− | * [http://www.osgi.org/javadoc/r4v42/org/osgi/framework/BundleActivator.html BundleActivator]
| |
− | ----------
| |
− | <h4>2. Define the Bundle Service Interface</h4>
| |
− | | |
− | <h5>2.1 Define the Java Interface that exposes the services</h5>
| |
− | Let us suppose that one wants to define a service that allows the user to find a book using its isbn.
| |
− | <source lang="java">
| |
− | package cs.ecl.osgi.simple.bookfinder;
| |
− | | |
− | public interface BookFinder {
| |
− | Book findBook(int isbn) throws BookNotFoundException;
| |
− | }
| |
− | </source>
| |
− | Define in the same bundle the classes that you need such as: Book and BookNotFoundException
| |
− | <source lang="java">
| |
− | package cs.ecl.osgi.simple.bookfinder;
| |
− | | |
− | public class Book {
| |
− | private int isbn;
| |
− | private String title;
| |
− |
| |
− | public Book(int isbn, String title) {
| |
− | super();
| |
− | this.isbn = isbn;
| |
− | this.title = title;
| |
− | }
| |
− | | |
− | public String getTitle() {
| |
− | return title;
| |
− | }
| |
− | | |
− | public void setTitle(String title) {
| |
− | this.title = title;
| |
− | }
| |
− | | |
− | public int getIsbn() {
| |
− | return isbn;
| |
− | }
| |
− | | |
− | public void setIsbn(int isbn) {
| |
− | this.isbn = isbn;
| |
− | }
| |
− | }
| |
− | | |
− | package cs.ecl.osgi.simple.bookfinder;
| |
− | | |
− | public class BookNotFoundException extends Exception {
| |
− | private static final long serialVersionUID = -6184839510952070091L;
| |
− | | |
− | public BookNotFoundException() {
| |
− | super();
| |
− | }
| |
− | | |
− | public BookNotFoundException(String arg0) {
| |
− | super(arg0);
| |
− | }
| |
− | }
| |
− | </source>
| |
− | | |
− | <h5>2.2 Define the MANIFEST.MF for the bundle ''cs.ecl.osgi.simple.bookfinder'' </h5>
| |
− | <source lang="xml">
| |
− | Manifest-Version: 1.0
| |
− | Bundle-ManifestVersion: 2
| |
− | Bundle-Name: Bookfinder
| |
− | Bundle-SymbolicName: cs.ecl.osgi.simple.bookfinder
| |
− | Bundle-Version: 1.0.0.qualifier
| |
− | Bundle-RequiredExecutionEnvironment: JavaSE-1.6
| |
− | Bundle-Vendor: Seneca College - Eclipse Course
| |
− | Export-Package: cs.ecl.osgi.simple.bookfinder
| |
− | </source>
| |
− | ----------
| |
− | | |
− | <h4>4. Define the Bundle Service Provider</h4>
| |
− | The service ''bookfinder'' could be used only if there is a bundle that implements the service. The bundle ''cs.ecl.osgi.simple.bookfinderservice'' implements ''BundleActivator'' interface in the ''Activator'' class. This bundle will be called 'service provider'.
| |
− | | |
− | <h5>4.1 Define the Activator class for the service provider</h5>
| |
− | <source lang="java">
| |
− | package cs.ecl.osgi.simple.bookfinderservice;
| |
− | | |
− | import org.osgi.framework.BundleActivator;
| |
− | import org.osgi.framework.BundleContext;
| |
− | | |
− | import cs.ecl.osgi.simple.bookfinder.BookFinder;
| |
− | import cs.ecl.osgi.simple.bookfinderservice.internals.BookFinderImplementation;
| |
− | | |
− | public class Activator implements BundleActivator {
| |
− | | |
− | private static BundleContext context;
| |
− | | |
− | static BundleContext getContext() {
| |
− | return context;
| |
− | }
| |
− |
| |
− | public void start(BundleContext bundleContext) throws Exception {
| |
− | Activator.context = bundleContext;
| |
− | BookFinder bookService = new BookFinderImplementation();
| |
− |
| |
− | context.registerService(BookFinder.class.getName(), bookService, null);
| |
− | System.out.println(" Bookfinder service registered ");
| |
− | }
| |
− |
| |
− | public void stop(BundleContext bundleContext) throws Exception {
| |
− | Activator.context = null;
| |
− | System.out.println(" Bookfinder service stopped ");
| |
− | }
| |
− | }
| |
− | </source>
| |
− | | |
− | <h5>3.2 Define the service implementation class </h5>
| |
− | The class must be defined in an internal package ''cs.ecl.osgi.simple.bookfinderservice.internals'' <u>The package will not be exposed to the outside world</u>
| |
− | | |
− | <source lang="java">
| |
− | package cs.ecl.osgi.simple.bookfinderservice.internals;
| |
− | | |
− | import cs.ecl.osgi.simple.bookfinder.Book;
| |
− | import cs.ecl.osgi.simple.bookfinder.BookFinder;
| |
− | import cs.ecl.osgi.simple.bookfinder.BookNotFoundException;
| |
− | | |
− | public class BookFinderImplementation implements BookFinder {
| |
− | private static final Book[] BOOKS = new Book[] {
| |
− | new Book(1234, "Java Programming Language"),
| |
− | new Book(5678, "OSGi") };
| |
− | | |
− | public Book findBook(int isbn) throws BookNotFoundException {
| |
− | Book found = null;
| |
− | | |
− | for (Book b : BOOKS)
| |
− | if (b.getIsbn() == isbn) {
| |
− | found = b;
| |
− | break;
| |
− | }
| |
− | if (found == null)
| |
− | throw new BookNotFoundException("No book with isbn = " + isbn);
| |
− | | |
− | return found;
| |
− | }
| |
− | }
| |
− | //This is a simple and trivial implementation.
| |
− | //There real implementation should use database, distributed system, etc.
| |
− | </source>
| |
− | | |
− | <h5>3.3 Define the MANIFEST.MF for the ''cs.ecl.osgi.simple.bookfinderservice'' bundle</h5>
| |
− | <source lang="xml">
| |
− | Manifest-Version: 1.0
| |
− | Bundle-ManifestVersion: 2
| |
− | Bundle-Name: Bookfinderservice
| |
− | Bundle-SymbolicName: cs.ecl.osgi.simple.bookfinderservice
| |
− | Bundle-Version: 1.0.0.qualifier
| |
− | Bundle-Activator: cs.ecl.osgi.simple.bookfinderservice.Activator
| |
− | Bundle-ActivationPolicy: lazy
| |
− | Bundle-RequiredExecutionEnvironment: JavaSE-1.6
| |
− | Import-Package: org.osgi.framework;version="1.3.0"
| |
− | Bundle-Vendor: Seneca College - Eclipse Course
| |
− | Export-Package: cs.ecl.osgi.simple.bookfinderservice
| |
− | Require-Bundle: cs.ecl.osgi.simple.bookfinder;bundle-version="1.0.0"
| |
− | </source>
| |
− | | |
− | The bundle export only the package ''cs.ecl.osgi.simple.bookfinderservice'' Meanwhile, the implementation package - ''cs.ecl.osgi.simple.bookfinderservice.internals'' - <strong>is hidden to the outside world and can be changed dynamically any time a better implementation is created</strong>.
| |
− | | |
− | The bundle provider requires the osgi framework and the interface bundle (e.g. ''cs.ecl.osgi.simple.bookfinder'' bundle)
| |
− | | |
− | : ''Require-Bundle'': cs.ecl.osgi.simple.bookfinder;bundle-version="1.0.0"
| |
− | : ''Import-Package'': org.osgi.framework;version="1.3.0"
| |
− | | |
− | The bundle'' cs.ecl.osgi.simple.bookfinderservice'' export its service, namely the bood finder service:
| |
− | | |
− | : ''Export-Package'': cs.ecl.osgi.simple.bookfinderservice
| |
− | | |
− | ----------
| |
− | | |
− | <h4>4. Define the Bundle Service Consumer</h4>
| |
− | The service ''bookfinder'' could be used only if there is a bundle that requests its service. The bundle ''cs.ecl.osgi.simple.bookfindconsumer'' by the time is activated ''BundleActivator'' looks for the service in the registry. This bundle will be called 'service consumer'.
| |
− | | |
− | <h5>4.1 Define the Activator class for the service consumer</h5>
| |
− | <source lang="java">
| |
− | package cs.ecl.osgi.simple.bookfinderconsumer.bookfinderconsumer;
| |
− | | |
− | import org.osgi.framework.BundleActivator;
| |
− | import org.osgi.framework.BundleContext;
| |
− | import org.osgi.framework.ServiceReference;
| |
− | | |
− | import cs.ecl.osgi.simple.bookfinder.BookFinder;
| |
− | import cs.ecl.osgi.simple.bookfinder.BookNotFoundException;
| |
− | | |
− | public class Activator implements BundleActivator {
| |
− | | |
− | private static BundleContext context;
| |
− | private BookFinder finderService;
| |
− | | |
− | static BundleContext getContext() {
| |
− | return context;
| |
− | }
| |
− | | |
− | public void start(BundleContext bundleContext) throws Exception {
| |
− | Activator.context = bundleContext;
| |
− | | |
− | ServiceReference reference = context
| |
− | .getServiceReference(BookFinder.class.getName());
| |
− | if (reference != null) {
| |
− | finderService = (BookFinder) context.getService(reference);
| |
− | | |
− | if (finderService != null) {
| |
− | printBook(finderService);
| |
− | context.ungetService(reference);
| |
− | } else
| |
− | System.err.println("the service cannot be used !!!");
| |
− | } else
| |
− | System.err.println("the service cannot be found !!!");
| |
− | | |
− | }
| |
− | | |
− | public void stop(BundleContext bundleContext) throws Exception {
| |
− | Activator.context = null;
| |
− | System.err.println("consumer bundle stopped");
| |
− | }
| |
− | | |
− | public void printBook(BookFinder finderService) {
| |
− | try {
| |
− | String s = finderService.findBook(1234).getTitle();
| |
− | | |
− | System.out.print("Book found: " + s + " !!!");
| |
− | } catch (BookNotFoundException ex) {
| |
− | System.err.println(ex.getMessage());
| |
− | }
| |
− | }
| |
− | }
| |
− | </source>
| |
− | | |
− | Steps to find and use the service:
| |
− | | |
− | 1. Look for the service reference in the bundle context:
| |
− | | |
− | The Framework returns ''ServiceReference'' objects from the ''BundleContext.getServiceReference'' method.
| |
− | A ''ServiceReference'' object may be shared between bundles and can be used:
| |
− | 1. to examine the properties of the service
| |
− | 2. to get the service object.
| |
− | | |
− | <b>ServiceReference reference = context.getServiceReference(BookFinder.class.getName());</b>
| |
− |
| |
− | 2. Look for the service object referenced by the specified ''ServiceReference'' object, namely the ''reference'' variable obtained at the first step.
| |
− | if (reference != null)
| |
− | <b> finderService = (BookFinder) context.getService(reference);</b>
| |
− | | |
− | 3. If the service reference is valid, invoke its services and <b>release the service object</b> referenced by the specified ''ServiceReference'' object.
| |
− | <source lang="java">
| |
− | if (finderService != null) {
| |
− | // invoke the services
| |
− | context.ungetService(reference);
| |
− | }
| |
− | </source>
| |
− | | |
− | The ''class org.osgi.framework.BundleContext'' defines the bundle's execution context within the Framework. The context is used to grant access to other methods so that this bundle can interact with the Framework.
| |
− | | |
− | BundleContext methods allow a bundle to:
| |
− | | |
− | * Subscribe to events published by the Framework.
| |
− | * Register service objects with the Framework service registry.
| |
− | * Retrieve ServiceReferences from the Framework service registry.
| |
− | * Get and release service objects for a referenced service.
| |
− | * Install new bundles in the Framework.
| |
− | * Get the list of bundles installed in the Framework.
| |
− | * Get the Bundle object for a bundle.
| |
− | | |
− | <h5>4.2 Define the MANIFEST.MF for the ''cs.ecl.osgi.simple.bookfinderconsumer'' bundle</h5>
| |
− | <source lang="xml">
| |
− | Manifest-Version: 1.0
| |
− | Bundle-ManifestVersion: 2
| |
− | Bundle-Name: Bookfinderconsumer
| |
− | Bundle-SymbolicName: cs.ecl.osgi.simple.bookfinderconsumer
| |
− | Bundle-Version: 1.0.0.qualifier
| |
− | Bundle-Activator: cs.ecl.osgi.simple.bookfinderconsumer.bookfinderconsumer.Activator
| |
− | Bundle-RequiredExecutionEnvironment: JavaSE-1.6
| |
− | Import-Package: cs.ecl.osgi.simple.bookfinder,
| |
− | org.osgi.framework;version="1.3.0"
| |
− | Bundle-Vendor: Seneca College - Eclipse Course
| |
− | Require-Bundle: org.eclipse.osgi;bundle-version="3.6.1"
| |
− | </source>
| |