- 浏览: 54105 次
- 性别:
- 来自: 深圳
最近访客 更多访客>>
最新评论
-
flhuang:
楼主太强了,估计以前也是研究轰炸机的
(转) TOMCAT源码分析(启动框架) -
afadgaeg:
好文章
(转) TOMCAT源码分析(消息处理) -
switchlau:
转注:
board:表示棋盘
tile: 表示L型骨牌的编号
...
分治法解决棋盘覆盖问题 -
sagah:
好文,正在研究这块!受用。
(转) ClassLoader Mechanism
This story appeared on JavaWorld at
http://www.javaworld.com/javaworld/jw-03-2008/jw-03-osgi1.html
Hello, OSGi, Part 1: Bundles for beginners
Creating, executing, and managing bundles in an OSGi container
By Sunil Patil, JavaWorld.com, 03/04/08
The Open Services Gateway Initiative (OSGi) defines an architecture for developing and deploying modular applications and libraries. In this first article in a three-part introduction to OSGi, Sunil Patil gets you started with OSGi development concepts and shows you how to build a simple Hello World application using the Eclipse OSGi container implementation, Equinox. He also touches briefly on building service-oriented applications using OSGi and introduces OSGi's ServiceFactory
and ServiceTracker
classes.
The Open Services Gateway Initiative (OSGi) , also known as the Dynamic Module System for Java , defines an architecture for modular application development. OSGi container implementations such as Knopflerfish , Equinox , and Apache Felix allow you to break your application into multiple modules and thus more easily manage cross-dependencies between them.
Similar to the Java Servlet and EJB specifications, the OSGi specification defines two things: a set of services that an OSGi container must implement and a contract between the container and your application. Developing on the OSGi platform means first building your application using OSGi APIs, then deploying it in an OSGi container. From a developer's perspective, OSGi offers the following advantages:
- You can install, uninstall, start, and stop different modules of your application dynamically without restarting the container.
- Your application can have more than one version of a particular module running at the same time.
- OSGi provides very good infrastructure for developing service-oriented applications, as well as embedded, mobile, and rich internet apps.
Given that you use servlet containers for building Web applications and EJB containers for building transactional applications, you may be wondering why you need yet another type of container. The short answer is that OSGi containers are intended specifically for developing complex Java applications that you want to break up into modules. I'll expand on that short answer throughout this series.
OSGi in enterprise applications
Work on the OSGi specification was started by the OSGi Alliance in March 1999. Its main goal was to create an open specification for delivering managed services to local networks and devices. The basic idea is that once you add an OSGi Service Platform to a networked device (embedded as well as servers), you should be able to manage the lifecycle of software components in that device from anywhere in the network. Software components can be installed, updated, or removed on the fly without ever having to disrupt the operation of the device.
For years, OSGi technology has flourished in the embedded systems and network devices market. Now, thanks in part to Eclipse, OSGi is emerging as a viable and valuable technology for enterprise development.
Growing support for OSGi
In 2003, the Eclipse development team began looking for ways to make Eclipse a more dynamic rich client platform and increase the toolset's modularity. Eventually, the team settled on using the OSGi framework as a runtime component model. Eclipse 3.0, released in June of 2004, was the first version of Eclipse based on OSGi.
Almost all enterprise application servers support or plan to support OSGi . The Spring framework also supports OSGi, via the Spring Dynamic Modules for OSGi Service Platforms project, which provides an infrastructure layer to make it easier to use OSGi in Spring-based Java enterprise application development.
Open source OSGi containers
From an enterprise developer's point of view, the OSGi container has such a low footprint that you can easily embed it into an enterprise application. For example, let's say you're developing a complex Web application. You want to break the application into multiple modules: one module for the view layer, another for the DAO layer, and a third module for the data access layer. Using an embedded OSGi container to manage the cross-dependencies of these modules would enable you to update your DAO layer (say from slow DAO to fast DAO) without restarting your application.
As long as your application is compliant with the OSGi specification it should be able to run in any OSGi-compliant container. Currently, there are three popular open source OSGi containers:
- Equinox is the reference implementation for the framework portion of the OSGi Service Platform Release 4. It is the modular Java runtime at the heart of the Eclipse IDE, and implements all of the mandatory and most of the optional features of the OSGi R4 specification.
- Knopflerfish is an open source implementation of the OSGi R3 and OSGi R4 specifications. Knopflerfish 2 implements all the mandatory features and some of the optional features defined in the R4 specification.
- Apache Felix is the open source OSGi container from the Apache Software Foundation. At the time of writing this container is not fully compliant with the OSGI R4 specification.
In this article we will use Equinox as our OSGi container. See the Resources section for more information about Apache Felix and Knopflerfish .
<!-- -->
Developing a Hello World bundle
In OSGi, software is distributed in the form of a bundle . A bundle consists of Java classes and other resources that deliver functions to device owners, as well as providing services and packages to other bundles. Eclipse offers excellent support for developing OSGi bundles. Not only does it provide wizards for creating OSGi bundles, it also has an embedded Equinox OSGi container that you can use to execute and debug OSGi plugins. Note that every Eclipse plug-in is essentially an OSGi bundle with some additional Eclipse-specific code. Eclipse also allows you to build standard-compliant OSGi bundles without code specific to Eclipse. In this section you'll learn how to develop a Hello World OSGi bundle using the Eclipse IDE.
Creating the bundle
Follow the steps below to create a Hello World bundle using OSGi and Eclipse.
- In Eclipse, click on File --> New --> Project . A New Project dialog will open.
- In the New Project dialog, select Plug-in Project and click Next. The Plug-in Project dialog will open.
- In the Plug-in Project dialog, enter the following values:
- Project Name:
com.javaworld.sample.HelloWorld
- Target Platform: OSGi framework --> Standard
- Project Name:
- Use default values for the remaining input and click Next. The Plug-in Context dialog will open.
- Select the default values for the Plug-in Context dialog and click Next.
- In the Templates dialog you'll find only one entry in Available Templates: Hello OSGi Bundle. Select it and click Finish.
Eclipse will take few seconds to generate template code for the Hello World bundle. It will create two files: Activator.java
and MANIFEST.MF
. We'll take a closer look at them both.
Activator.java
Your Activator.java
file should look as shown in Listing 1.
Listing 1. Activator.java
package com.javaworld.sample.helloworld;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public class Activator implements BundleActivator {
public void start(BundleContext context) throws Exception {
System.out.println("Hello world");
}
public void stop(BundleContext context) throws Exception {
System.out.println("Goodbye World");
}
}
If your bundle needs to be notified at the time of bundle startup or shutdown then you should create a class implementing the BundleActivator
interface. Follow these rules when creating the class:
- The
BundleActivator
class must have a public constructor that takes no parameters. The OSGi framework can create aBundleActivator
object by callingClass.newInstance()
. - The container will call the
start()
method of yourActivator
class to start the bundle. The bundle can take this opportunity to perform resource initialization such as getting a database connection for future use. Thestart()
method takes one argument, theBundleContext
object. This object allows bundles to interact with the framework by providing access to OSGi-container-related information. If an exception is thrown for a particular bundle the container will mark that bundle as stopped and will not put it into service. - The container will call the
stop()
method of yourActivator
class to report that it is shutting down a bundle. You can use this opportunity to perform cleanup tasks such as releasing the database connection.
Once your Activator
class is ready you should relay its fully qualified name to the container using your MANIFEST.MF
file.
MANIFEST.MF
The MANIFEST.MF
file acts as deployment descriptor for your bundle. The format for this file is the same as that of a normal JAR file, so it consists of a set of headers with values. The OSGi specification defines a set of headers that you can use to describe your bundle to the OSGi container. The MANIFEST.MF file for your Hello World bundle should look as shown in Listing 2.
Listing 2. Manifest for the Hello World bundle
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: HelloWorld Plug-in
Bundle-SymbolicName: com.javaworld.sample.HelloWorld
Bundle-Version: 1.0.0
Bundle-Activator: com.javaworld.sample.helloworld.Activator
Bundle-Vendor: JAVAWORLD
Bundle-Localization: plugin
Import-Package: org.osgi.framework;version="1.3.0"
Let's take a closer look at what each of these headers is used for:
Bundle-ManifestVersion
header tells the OSGi container that this bundle follows the rules of the OSGi specification. A value of 2
means that the bundle is compliant with OSGi specification Release 4; a value of 1
means that it is compliant with Release 3 or earlier. Bundle-Name
header defines a short, human-readable name for the bundle. Bundle-SymbolicName
header specifies a unique, non-localizable name for the bundle. This is the name you will use while referring a given bundle from other bundles. Bundle-Version
header specifies the version of the bundle. Bundle-Activator
header specifies the name of the optional listener class to be notified of bundle start
and stop
events. In Listing 2 the value of this header is com.javaworld.sample.helloworld.Activator
. Bundle-Vendor
header contains a human-readable description of the bundle vendor. Bundle-Localization
header contains the location in the bundle where localization files can be found. The Hello World bundle doesn't contain any locale-specific files, but the eclipse IDE still generates this header. Import-Package
header defines imported packages for the bundle. You'll learn more about this when I discuss dependency management, later in the article. The Hello World bundle is ready, so let's execute it to see the output.
Executing a bundle
As I mentioned earlier, the Eclipse IDE has an embedded Equinox OSGi container that you can use to execute or debug OSGi bundles. Follow these steps to execute the Hello World bundle:
- Click on Run --> Run .
- Eclipse will open the dialog called "Create, manage and run configuration." In that dialog, double-click the Equinox OSGi Framework button and it will open a runtime configuration dialog box.
- In that dialog, change the value of the Name field to
Hello World Bundle
. - You will notice that in the Plug-ins section under the Workspace plug-in there is an entry for the
com.javaworld.sample.HelloWorld
plugin, which is checked. Under Target Platform, make sure that the checkbox next to theorg.eclipse.osgi
plugin is also checked.Your Run dialog should look like the screenshot in Figure 1 (click to enlarge).Figure 1. Create a configuration to launch the Equinox OSGi framework
- Now click the Run button. You should see a "Hello world" message in the IDE's console view. Note that Eclipse actually opens the OSGi console in its console view.
<!-- -->
The OSGi console
The OSGi console is a command-line interface to the OSGi container. It allows you to do things like start, stop, install bundles, and update or delete bundles. In your Eclipse IDE, click the console view to give focus to that view, then click Enter and you will get an OSGi prompt like the one shown in Figure 2 (click to enlarge).
Figure 2. HelloWorldActivator.java in the OSGi console
Here are some of the commonly used OSGi commands that you can use to interact with your OSGi container:
-
ss
displays a list of installed bundles with the status of each bundle. It will display the bundle ID, short name, and status of the bundle. -
start <bundleid>
starts a bundle. -
stop <bundleid>
stops a bundle. -
update <bundleid>
updates a bundle with a new JAR file. -
install <bundleURL>
installs a new bundle into the OSGi container. -
uninstall <bundleid>
uninstalls already installed bundles from the OSGi container.
Note that these commands are defined in the OSGi specification so you can use them to interact with any of the OSGi containers.
Dependency management
The OSGi specification allows you to break your application into multiple modules and then manage their dependencies on each other. It does this by adding a bundle scope . By default, none of the classes in a bundle are visible from any other bundle; inside bundles they follow the normal rules of the Java language. So, what do you do if you want to access the classes of one bundle from another bundle? The solution is to export packages from the source bundle and then import them into the target bundle. In this section we'll walk through a sample application that demonstrates this concept.
First, we will create a com.javaworld.sample.HelloService
bundle, which will export a package. Then we will import the package into our com.javaworld.sample.HelloWorld
bundle.
Exporting a package
We'll start by creating the com.javaworld.sample.HelloService
bundle and exporting a package from it. Follow these steps to create the bundle and export the package:
- Create the
com.javaworld.sample.HelloService
bundle by following the same steps used to create thecom.javaworld.sample.HelloWorld
bundle in the previous section. - Inside the
HelloService
bundle, create acom.javaworld.sample.service.HelloService.java
interface, as shown in Listing 3.Listing 3. HelloService.java
public interface HelloService { public String sayHello(); }
- Now create a
com.javaworld.sample.service.impl.HelloServiceImpl.java
class implementing theHelloService
interface, as shown in Listing 4.Listing 4. HelloServiceImpl.java
public class HelloServiceImpl implements HelloService{ public String sayHello() { System.out.println("Inside HelloServiceImple.sayHello()"); return "Say Hello"; } }
- Open the
MANIFEST.MF
for theHelloService
package in your Eclipse Manifest editor and go to the Runtime tab. In the Exported Packages section, click Add and select thecom.javaworld.sample.service
package. TheMANIFEST.MF
file for theHelloService
bundle should look like the one in Listing 5.Listing 5. Manifest for HelloService bundle
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: HelloService Plug-in Bundle-SymbolicName: com.javaworld.sample.HelloService Bundle-Version: 1.0.0 Bundle-Vendor: JAVAWORLD Bundle-Localization: plugin Export-Package: com.javaworld.sample.service Import-Package: org.osgi.framework;version="1.3.0"
As you can see, the MANIFEST.MF
file for the HelloService
bundle looks very similar to that of the HelloWorld
bundle. The only difference is that this MANIFEST.MF
file has one Export-Package
manifest header, whose value is com.javaworld.simple.service
.
The Export-Package
manifest header informs the OSGi container that classes in the com.javaworld.sample.service
package from the HelloService
bundle can be accessed from outside. Note that in the sample code we have exposed a HelloService
interface but not the HelloServiceImpl
implementation class.
Importing a package
The next step is to update the HelloWorld
bundle to import the com.javaworld.simple.service
package. Here are the steps to import the package:
- In the
com.javaworld.sample.HelloWorld
bundle, open theMANIFEST.MF
file in the Plug-in Manifest editor. Now go to the Dependencies tab, and then to Imported Packages . Addcom.javaworld.sample.service
as the value of Imported Packages. TheMANIFEST.MF
file for yourHelloWorld
bundle should look like the one in Listing 6.Listing 6. Manifest for the updated HelloWorld bundle
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: HelloWorld Plug-in Bundle-SymbolicName: com.javaworld.sample.HelloWorld Bundle-Version: 1.0.0 Bundle-Activator: com.javaworld.sample.helloworld.Activator Bundle-Vendor: JAVAWORLD Bundle-Localization: plugin Import-Package: com.javaworld.sample.service, org.osgi.framework;version="1.3.0"
As you can see, the value of theImport-Package
header is a comma-separated list of packages that this bundle wants to import. In the sample code theHelloWorld
bundle imports two packages:com.javaworld.sample.service
andorg.osgi.framework
.
Theorg.osgi.framework
package contains OSGi framework classes such asBundleContext
andBundleActivator
, which are used by theActivator.java
class of theHelloWorld
bundle. - Next, open
com.javaworld.sample.helloworld.Activator.java
in the Eclipse Java editor. You will notice that you are now able to access theHelloService
interface but not theHelloServiceImpl
class. This is because theHelloService
package exports (and theHelloWorld
package imports) thecom.javaworld.sample.service
package.HelloServiceImpl
is an internal class for theHelloService
bundle and no other bundle can access it.
<!-- -->
Class-level scope
If you try running the sample service package now it will print "Hello World" on your Eclipse console. If you try running Activator.java
to access HelloServiceImpl.java
and compile it with the normal javac
complier, it will compile. If you try to execute this bundle in an OSGi container, however, it will throw an exception.
How is the OSGi container able to hide a few classes from the .jar file while others are visible? The answer is that the OSGi container uses the Java class loader to manage class visibility. The OSGi container creates a different class loader for every bundle. The bundle can therefore access classes from
-
Boot classpath
: Contains the
java.*
packages. - Framework classpath : Usually has a separate class loader for the framework implementation classes as well as key service interface classes.
- Bundle space : Consists of the JAR file that is associated with the bundle plus any additional JARs that are closely tied to the bundle, like fragments.
-
Imported packages
: For instance, the
HelloWorld
bundle imports thecom.javaworld.sample.service
package so it can access classes from that package.
The bundle-level scope is a powerful feature allowing you (for instance) to safely change the HelloServiceImpl.java
class without worrying that dependent code might break.
OSGi services
As previously mentioned, the OSGi architecture is a very good candidate for implementing service-oriented applications. It allows bundles to export services that can be consumed by other bundles without knowing anything about the exporting bundle. Taken with the ability to hide the actual service implementation class, OSGi provides a perfect combination for service-oriented applications.
In OSGi, a source bundle registers a POJO (you don't have to implement any interfaces or extend from any superclass) with the OSGi container as a service under one or more interfaces. The target bundle can then ask the OSGi container for services registered under a particular interface. Once the service is found, the target bundle binds with it and can start calling its methods. As with other OSGi concepts, a sample application will make all of this more clear.
Exporting services
In this section we will change the HelloService
bundle so that it exports objects of the HelloServiceImpl.java
class as a service. Here are the steps to set up the sample application:
- Change the
MANIFEST.MF
forcom.javaworld.sample.HelloService
to import theorg.osgi.framework
package. - Create the
com.javaworld.sample.service.impl.HelloServiceActivator.java
as shown in Listing 7.Listing 7. Create HelloServiceActivator.java
public class HelloServiceActivator implements BundleActivator { ServiceRegistration helloServiceRegistration; public void start(BundleContext context) throws Exception { HelloService helloService = new HelloServiceImpl(); helloServiceRegistration =context.registerService(HelloService.class.getName(), helloService, null); } public void stop(BundleContext context) throws Exception { helloServiceRegistration.unregister(); } }
Note that the source bundle should use theBundleContext.registerService()
method to export the service. It takes three parameters:- The name of the interface under which you want to register the service. If you want to register the service under multiple interfaces then you should create a
String
array of interface names and pass it as your first argument. In the sample code we want to export the service under the name ofHelloService
interface. - The actual Java object that you want to register as a service. In our sample code we are exporting objects of the
HelloServiceImpl
class as the service. - Properties of the service, in this case a
Dictionary
object. If more than one bundle exports a service under the same interface name then the target object can use these properties to filter out the service that it is interested in.
- The name of the interface under which you want to register the service. If you want to register the service under multiple interfaces then you should create a
- The last step is to change the
MANIFEST.MF
file of theHelloService
bundle to declareHelloServiceActivator
as the bundle's activator class. To do that, simply addcom.javaworld.sample.service.impl.HelloServiceActivator
as the value of theBundle-Activator
header in yourMANIFEST.MF
file.
Now the HelloService
bundle is ready to export objects of the HelloServiceImpl
class. When the OSGi container starts the HelloService
bundle it will pass control to HelloServiceActivator.java
, which will register an object of HelloServiceImpl
as a service. The next step is to create the service consumer.
Importing the service
In this section we will change the HelloWorld
bundle developed in the last section so that it acts as a consumer of the HelloService
service. The main thing you need to do is change the Activator.java
for the HelloWorld
bundle as shown in Listing 8.
Listing 8. HelloWorldActivator.java
public class Activator implements BundleActivator {
ServiceReference helloServiceReference;
public void start(BundleContext context) throws Exception {
System.out.println("Hello World!!");
helloServiceReference= context.getServiceReference(HelloService.class.getName());
HelloService helloService =(HelloService)context.getService(helloServiceReference);
System.out.println(helloService.sayHello());
}
public void stop(BundleContext context) throws Exception {
System.out.println("Goodbye World!!");
context.ungetService(helloServiceReference);
}
}
The BundleContext.getServiceReference()
method returns a ServiceReference
object for a service registered under the HelloService
interface. If multiple such services exist, the service with the highest ranking (as specified in its Constants.SERVICE_RANKING
property) is returned. Once you have the object of ServiceReference
you can call its BundleContext.getService()
method to get the actual service object.
You can run this sample the same way you would execute any bundle, by clicking Run --> Run
Simply make sure that both the HelloWorld
and HelloService
bundles are checked in as plugins. When you start the HelloService
bundle, you will see the message "Inside HelloServiceImple.sayHello()
" printed from the HelloServiceImpl.sayHello()
method.
<!-- -->
Creating a service factory
In the last section you learned how to use the OSGi framework to create a Java object and register it as service to be consumed by any other bundle. If you look at the HelloServiceActivator.start()
method you will notice that we created an object of the HelloServiceImpl
class in the start method and registered it under the name of HelloService
interface. Thereafter, whenever any bundle asks for the HelloService
service, the OSGi container will return the same object.
This implementation will work for most common use cases. But let's say you want to return a different object of the HelloServiceImpl
class for every consumer bundle. Alternately, let's say your service object needs to open a connection to a database and you don't want to open the connection unless someone really needs the service.
In either case, the solution is to create a class implementing the ServiceFactory
interface and register its object, instead of the actual service object, as a service. Once you do that, your ServiceFactory
class will take control whenever any bundle requests the service. ServiceFactory
will create a new object of Service
for every bundle, and will also delay creation of the actual service until someone really needs it.
Follow these steps to change the implementation of the com.javaworld.sample.HelloService
bundle developed in the last section to use a ServiceFactory
:
- Create the factory class
HelloServiceFactory.java
, as shown in Listing 9.Listing 9. Create HelloServiceFactory.java
public class HelloServiceFactory implements ServiceFactory{ private int usageCounter = 0; public Object getService(Bundle bundle, ServiceRegistration registration) { System.out.println("Create object of HelloService for " + bundle.getSymbolicName()); usageCounter++; System.out.println("Number of bundles using service " + usageCounter); HelloService helloService = new HelloServiceImpl(); return helloService; } public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) { System.out.println("Release object of HelloService for " + bundle.getSymbolicName()); usageCounter--; System.out.println("Number of bundles using service " + usageCounter); } }
TheServiceFactory
interface defines two methods:-
getService()
: The OSGi framework invokes this method the first time the specified bundle requests a service object using the
BundleContext.getService(ServiceReference)
method. In Listing 9, we use this method to create a different object ofHelloServiceImpl
for every bundle, and we return that object. The OSGi framework caches the value returned (unless it is null), and will return the same service object on any future calls toBundleContext.getService()
from the same bundle. -
ungetService()
: The OSGi container invokes this method when a service has been released by a bundle. The service object may then be destroyed. In Listing 9, we use this method to reduce the
usageCount
of the service and print the number of clients for the service.
-
getService()
: The OSGi framework invokes this method the first time the specified bundle requests a service object using the
- Change
HelloServiceActivator.java
and modify thestart()
method of your activator so that it will register objects ofServiceFactory
instead ofHelloService
, as shown in Listing 10:Listing 10. Changes to HelloServiceActivator.java
public class HelloServiceActivator implements BundleActivator { ServiceRegistration helloServiceRegistration; public void start(BundleContext context) throws Exception { HelloServiceFactory helloServiceFactory = new HelloServiceFactory(); helloServiceRegistration =context.registerService(HelloService.class.getName(), helloServiceFactory, null); } public void stop(BundleContext context) throws Exception { helloServiceRegistration.unregister(); } }
Now try running this sample code. You should notice that it prints the service usage count as one (1) when HelloWorld
bundle is started and zero (0) when the HelloWorld
bundle is stopped.
Tracking services
In the "OSGi services" section you learned how to search for a service using its interface name. But what happens if more than one bundle registers a service under the same interface name? In that case the OSGi container will return the service with the highest ranking -- that is, the service that is registered with the highest valued SERVICE_RANKING
property. If more than one service has an equally valued SERVICE_RANKING
property, then the OSGi container will return the service with the lowest PID.
But let's say that you are creating a consumer that needs to know whenever an object is registered or unregistered under a particular interface. In this situation, you should use the ServiceTracker
class. Let's see what happens when we change the sample code to utilize a service tracker, as described below.
- Change the
MANIFEST.MF
for yourHelloWorld
bundle to import theorg.osgi.util.tracker
package. - Create
HelloServiceTracker.java
as shown in Listing 11.Listing 11. HelloServiceTracker.java
public class HelloServiceTracker extends ServiceTracker { public HelloServiceTracker(BundleContext context) { super(context, HelloService.class.getName(),null); } public Object addingService(ServiceReference reference) { System.out.println("Inside HelloServiceTracker.addingService " + reference.getBundle()); return super.addingService(reference); } public void removedService(ServiceReference reference, Object service) { System.out.println("Inside HelloServiceTracker.removedService " + reference.getBundle()); super.removedService(reference, service); } }
As you can see in the constructor of theHelloServiceTracker
class, we are passing the name of theHelloService
interface to its super class, which is the equivalent of saying thatHelloServiceTracker
should track services registered under theHelloService
interface name. TheHelloServiceTracker
class extends theServiceTracker
class and implements two methods:- addingService() is called when a bundle registers a service under the given interface name.
- removedService() is called when a bundle unregisters a service under the given interface name.
- Change
Activator.java
so that it starts using theHelloServiceTracker
class to manage services instead of looking them up directly, as shown in Listing 12.Listing 12. Activator.java uses HelloServiceTracker
public class Activator implements BundleActivator { HelloServiceTracker helloServiceTracker; public void start(BundleContext context) throws Exception { System.out.println("Hello World!!"); helloServiceTracker= new HelloServiceTracker(context); helloServiceTracker.open(); HelloService helloService = (HelloService)helloServiceTracker.getService(); System.out.println(helloService.sayHello()); } public void stop(BundleContext context) throws Exception { System.out.println("Goodbye World!!"); helloServiceTracker.close(); } }
In the initialstart()
method we first create aHelloServiceTracker
object, then we askHelloServiceTracker
to start tracking the underlying service. A call togetService()
will now get theHelloService
object.
If you try executing this sample you will notice that whenever you start or stop the HelloService
bundle it will result in a call to either the addingService()
or removedService()
method of the HelloServiceTracker
object.
In conclusion
In this first article in the three-part Hello, OSGi series, I've introduced you to the basic concepts of modular application development with OSGi. You've learned about the three currently available open source OSGi containers and walked through the steps to develop a simple component bundle using Equinox, the fully OSGi-compliant Eclipse container. You've also learned how bundles can interact by importing and exporting each other's packages and services.
In this article you may have noticed one of the challenges of developing OSGi bundles: that each of your bundles needs to be aware of OSGi AP. In some development scenarios this could mean writing a lot of infrastructure code. In the next article in the Hello, OSGi series I'll introduce you to the Spring Dynamic Modules for OSGi Service Platforms project, which simplifies development of Spring-based OSGi bundles. See the Resources section in the meantime, to learn more about OSGi .
About the author
Sunil Patil is a Java Enterprise/Portlet developer working for Ascendant Technology in San Francisco, California. He is the author of Java Portlets 101 (SourceBeat, April 2007) and has written numerous articles published by O'Reilly Media. Sunil was a member of IBM's WebSphere Portal Server development team for three years and is actively involved in the Pluto community. In addition to being an IBM Certified WebSphere Portal Server Application Developer for both v5.0 and v5.1, he is a Sun Microsystems Certified Java Programmer, a Web component developer, and a business component developer. You can view Sunil's blog at http://jroller.com/page/SunilPatil .
All contents copyright 1995-2008 Java World, Inc. http://www.javaworld.com
发表评论
-
(转)Hello, OSGi, Part 3: Take it to the server side
2008-10-09 13:26 2778This story appeared on JavaWorl ... -
(转) osgi介绍(一)什么是osgi
2008-09-06 21:10 1764http://www.blogjava.net/Ferrari ... -
深入理解String对象(整理)
2008-06-25 12:43 897深入研究 String String是一个非可变类(immut ... -
(转) Tomcat启动分析
2008-06-10 17:19 8901 - Tomcat Server的组成部 ... -
(转) TOMCAT源码分析(消息处理)
2008-06-10 16:30 11230:前言 我们知道了tomcat的整体框架了, 也明白了 ... -
(转) TOMCAT源码分析(启动框架)
2008-06-10 16:27 1073http://dev.csdn.net/develop/ar ... -
访问java核心包中的包可访问成员
2008-06-03 13:04 934本文介绍如何访问java核心包中的包可访问成员。包可访问性的成 ... -
(转) ClassLoader Mechanism
2008-06-03 12:44 1076http://dev2dev.bea.com.cn/bbs/t ... -
ClassLoader原理(转)
2008-05-17 15:19 1293http://jamesdu.bokee.com/349567 ...
相关推荐
第六章“Moving Toward Bundles”引导读者逐步了解如何将现有的Java应用程序转换为模块化的OSGi bundles。这一过程不仅涉及到代码级别的调整,还需要重新考虑应用程序的设计和架构,以充分利用OSGi所提供的模块化...
### OSGi与Spring:Spring DM开发环境配置详解 #### 一、引言 随着软件架构的不断发展,模块化和微服务化的趋势日益明显。在Java领域,OSGi(Open Service Gateway Initiative)作为一套成熟的技术标准,为实现模块...
OSGi(Open Services Gateway Initiative)是一个基于Java语言的服务平台,提供了一种动态化、模块化的应用程序架构。在OSGi架构中,整个生命周期管理是十分重要的组成部分,它保证了应用能够动态地进行安装、启动、...
在OSGi入门篇:模块层这篇文章中,作者静默虚空深入探讨了OSGi框架中模块层的基础知识以及设计模块层时OSGi联盟所做的考虑。OSGi模块层是框架中最基础的部分,它实现了Java的模块化特性,但又与Java现有的模块化特性...
OSGi(Open Service Gateway Initiative)是一个Java社区定义的模块化服务平台,它允许在同一个运行环境中部署多个版本的同一个组件,而不会相互冲突,从而提供了一个动态的、模块化的运行时环境。OSGi规范定义了...
"OSGi HelloWorld实例"是一个典型的入门教程,旨在帮助初学者理解如何在OSGi环境中创建和运行一个简单的程序。 首先,我们需要了解OSGi的基本概念: 1. **模块(Bundle)**:在OSGi中,模块是软件的基本单元,它们...
**IntelliJ IDEA OSGI HelloWorld程序详解** OSGi(Open Service Gateway Initiative)是一个Java模块化系统和标准,它允许开发人员将应用程序分解为独立的模块,这些模块可以在运行时动态地安装、卸载和升级,而不...
1. ** Felix或Equinox插件**:最常见的将OSGI引入Tomcat的方法是使用Felix或Equinox这两款流行的OSGI实现作为插件。这些插件提供了一个运行时环境,使得Tomcat可以加载和管理OSGI Bundle。 2. **类加载器调整**:...
【标题】"killbill-osgi-bundles-lib-slf4j-osgi-0.8.4.zip" 是一个基于OSGi的 Kill Bill 库,其中包含了SLF4J(Simple Logging Facade for Java)的OSGi兼容版本。SLF4J是一个为各种日志框架提供简单抽象的接口,...
1. **Framework Core**: This is the core component of OSGi and provides the basic functionality for managing bundles and services. 2. **Bundles**: Bundles are the fundamental units of modularity in ...
Java应用架构设计:模块化模式与OSGi 英文版 中文版介绍: 全球资深Java技术专家的力作,系统、全面地讲解如何将模块化设计思想引入开发中,涵盖18个有助于实现模块化软件架构的模式 中文目录: 第一部分 模块化的...
Spring OSGi是Spring框架与OSGi(Open Service Gateway Initiative)规范相结合的一种技术,它允许在OSGi容器中运行和管理Spring应用。OSGi是一种模块化系统,为Java应用程序提供了动态部署、版本控制和依赖管理的...
1. **OSGi框架**:OSGi是一种模块化系统,允许Java应用程序按需动态地安装、卸载和升级模块,提供了服务注册和服务发现机制,增强了软件的可维护性和可扩展性。 2. **Blueprint服务容器**:Apache Felix Blueprint...
简单的OSGi启动器 我讨厌复杂的发射器。 我只想运行OSGi项目,而无需进行配置和部署。 该项目提供了一个maven插件,该插件允许从OSGi捆绑包maven项目创建可执行的jar文件。 只需将所需的包指定为项目的运行时依赖...
凡人的OSGi 这是我在 NA 2011,EU 2012和EU 2014上的“ OSGi的凡人”演示文稿的代码。 这是使用OSGi Declarative Services从头开始构建的最小的独立RESTful服务器,旨在证明OSGi不仅适用于超人大师。 该示例演示了...
将生成的* -standalone.jar放入OSGI自动加载(bundles /)文件夹中 用法 支持以下非标准OSGI Manfiest标头 Clojure导入 Clojure出口 启用Clojure Clojure激活剂 Clojure导入和Clojure导出接受由cama分隔的版本化...