Reputation: 1030
I'm attempting to use Declarative Services to create a service bundle that provides functionality to another bundle. However, I want my Service Provider bundle to not start until it is needed. Let me describe my conditions.
There are two bundles:
-com.example.serviceprovider
-com.example.serviceconsumer
The Service Provider bundle provides a services using Declarative Services as follows:
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" enabled="true" immediate="true" name="samplerunnable1">
<implementation class="com.example.serviceprovider.SampleRunnable"/>
<service>
<provide interface="java.lang.Runnable"/>
</service>
The Service Consumer references the provided services as follows:
<reference name="SampleRunnable"
interface="java.lang.Runnable"
bind="setRunnable"
unbind="unsetRunnable"
cardinality="1..n"
policy="dynamic"/>
When both of these bundles are "ACTIVE" on start up, the Service Consumer has no trouble communicating with the service declared by the Service Provider. The problem happens when I try and have the service provider start in a lazy fashion.
After the Service Provider is set to load lazy this is what I get in the OSGi console:
osgi> ss
"Framework is launched."
id State Bundle
15 STARTING com.example.serviceconsumer_1.0.0.X
16 RESOLVED com.example.serviceprovider_1.0.0.X
What I would expect to see, is that even though bundle 16 is only "RESOLVED" that it would have at least registered is service. But when I call the "bundle" command, it states "No registered services."
osgi> bundle 16
com.example.serviceprovider_1.0.0.X [17]
Id=17, Status=RESOLVED Data Root=C:\apache\apache-tomcat-.0.40\work\Catalina\localhost\examplesX\eclipse\configuration\org.eclipse.osgi\bundles\17\data
"No registered services."
No services in use.
No exported packages
Imported packages
org.osgi.framework; version="1.7.0"<org.eclipse.osgi_3.8.0.v20120529-1548 [0]>
No fragment bundles
Named class space
com.example.serivceprovider; bundle-version="1.0.0.X"[provided]
No required bundles
Maybe I've missed the fundamental concept of lazy loaded bundles and services registration. If a bundle is in a "RESOLVED" state, shouldn't it have all it's "wires" connected? (ie, has a classloader, resolved import and export dependencies and services registered.) If the Service Consumer tries to access the service shouldn't that bundle transition to the "ACTIVE" state? What piece am I missing here?
Upvotes: 2
Views: 1991
Reputation: 15372
Declarative services were designed for this case. Starting a bundle means that's functionality should be available, it does not mean it actually uses resources. Only stop bundles when you don't want is function.
This question is a good example of trying to control too much. In a component oriented world programmers should use lazy initialisation as much as possible but they should never attempt to control the life cycle.
Upvotes: 2
Reputation: 23948
Bundles in the RESOLVED state cannot provide services, and they will be ignored by Declarative Services. You should in general start all bundles during launch time, even if you want lazy loading behaviour. The key is to make the activation of the bundles cheap (or free!), and only pay for initialization of components when they are required.
DS takes care of lazy activation by default already. There is nothing you need to enable or change for this to happen. Essentially DS publishes the service entry in the registry, but it does not actually instantiate your component (or even load its class) until some client tries to use the service.
Furthermore, because DS does not load the class until required, OSGi does not even need to create a ClassLoader for the bundle, so long as your bundle does not have a BundleActivator.
To reiterate, you should not seek to make your bundles stay in RESOLVED state. Such bundles can only export static code and resources, but they cannot "do" anything and they cannot participate in the service registry.
Upvotes: 4