The "One Laptop Per Child" project has a great device ready to ship, but there's no Java on there. Let's think about working together to put Java on OLPC!
Replies:
18 -
Pages:
2
[
12
| Next
]
Threads:
[
Previous
|
Next
]
Welcome back to the EclipseZone "Getting Started with OSGi" tutorial series. Before getting into today's lesson I'd like to remind you that you can find links to all the previous parts of the tutorial on the
contents page
on my personal blog.
Last time
we took our first look at Declarative Services. This time we will look at the service consumer side of Declarative Services. Remember that previously we registered a service under the
java.lang.Runnable
interface; now we will create a component that depends on that service.
As discussed, the Declarative Services specification is all about letting you focus on the application logic of your code, rather than the OSGi "glue" code that had to be written in previous lessons. With that in mind, we're simply going to dive into the code, but before we do that we need to create a project. Follow the same steps as in the last lesson, but use the project name "SampleImporter".
Now copy the following code from your browser and paste it into the
src
folder inside the newly created Eclipse project:
This class implements the
CommandProvider
interface, which is used to extend the set of commands available at the "osgi>" prompt when you run Equinox. The reason for writing a
CommandProvider
is that it provides a convenient way to test our code interactively. There is a more detailed discussion of command providers in
Chris Aniszczyk's
article
on IBM developerWorks.
Notice that we don't call any OSGi APIs in this class, in fact we don't even need to import anything from the
org.osgi.*
packages. The service that we depend on – in this case, an instance of
java.lang.Runnable
– is provided to us through the
setRunnable
method, and it is taken away using the
unsetRunnable
method. We can consider this a form of
dependency injection
.
The other two methods,
getHelp
and
_run
are the implementation methods for the command provider. Yes, "_run" is a funny name with its leading underscore, but that is just an odd feature of the Equinox console API, and nothing to do with OSGi or Declarative Services. Methods using the leading-underscore pattern become commands on the Equinox console, so by providing a method called
_run
we have added a "run" command. Another thing to notice about this class is that we're being careful to ensure that the runnable field is updated and accessed in a thread-safe way. Thread safety is particularly important in OSGi since it is intrinsically multithreaded, but frankly we should always write our code to be thread-safe.
As before, we have to provide an XML file containing the DS declarations to get this to work. Copy the following into
OSGI-INF/commandprovider1.xml
in your plug-in project:
There's another important step which I neglected to mention last time. (Thanks to Seamus Venasse for
pointing it out
.) You need to edit the
build.properties
file in your plug-in project, and check the box next to the
OSGI-INF
folder. This is necessary to ensure the folder is included when the bundle is exported using Eclipse's export wizard, or built using PDE Build.
Also we need to add the following line to the bundle manifest:
Service-Component: OSGI-INF/commandprovider1.xml
This declaration has two of the same elements that we saw before, the
implementation
and
service
nodes. The
implementation
node provides the name of the class which implements the component, and the
service
node tells DS to register the component as a service. In this case we are registering under the
CommandProvider
interface, which is how we let the Equinox console know about the existence of our command provider.
The next element called
reference
is something we haven't seen before – it declares to DS that our component has a dependency on a service. The
name
attribute is simply an arbitrary string which names the dependency (we don't need to worry yet about what this is used for) and the
interface
attribute specifies the name of the interface we depend on. The
bind
attribute is the name of a method in the implementation class that will be called by DS when a service becomes available, or in other words, when a Runnable service is registered with the Service Registry, DS will obtain a reference to the new service object and supply it to our component using the specified method. Likewise the
unbind
attribute is the name of a method that will be called by DS when a service we were using becomes unavailable.
The
cardinality
attribute reveals the real power of DS. This attribute controls whether the dependency is optional or mandatory, and whether it is singular or multiple. The possible values are:
0..1: optional and singular, "zero or one"
1..1: mandatory and singular, "exactly one"
0..n: optional and multiple, "zero to many"
1..n: mandatory and multiple, "one to many" or "at least one"
In this example we chose optional and singular, which means our command provider can cope with the dependent service being unavailable. Looking back at the code for the
_run
method, you can see it was necessary to do a null check to handle such a situation.
Let's see what happens if we run this bundle. If you still have your SampleExporter bundle from last time, then you should see the following response when you type the "run" command at the osgi> prompt:
Hello from SampleRunnable
Great! This confirms that we have successfully imported the Runnable service that we wrote in the last lesson. Now try using the
stop
command to turn off the SampleExporter bundle. When you type the "run" command again you should see:
Error, no Runnable available
Which means that DS noticed the Runnable service going away, and called our
unsetRunnable
method to let us know.
Looking again at the
cardinality
attribute, what do you think will happen if we change to "1..1", i.e. switch from an optional to a mandatory dependency? Try making that change and restarting Equinox. If the SampleExporter bundle is active when we type "run" then we will see the same message as before: "Hello from SampleRunnable". However, if SampleExporter is inactive then we will see a very different error message than before. In fact, we will see Equinox's console help message, which is its standard response to an unrecognized command. This indicates that our command provider itself has been unregistered by DS! Since the component has a mandatory dependency which cannot be satisfied, DS is forced to deactivate the component and unregister any services it was providing. That in turn means that the Equinox console forgets about the "run" command.
The ease with which we can make changes like this is one of the best reasons to use Declarative Services. Remember that with
ServiceTracker
we would have had to rewrite a fairly substantial piece of code.
You might be wondering about the
policy
attribute, since I haven't mentioned it yet. The value of this can be either "static" or "dynamic", and it states whether the component implementation is able to cope with having services dynamically switched. If it is not, then it is necessary for DS to deactivate the component and create a new instance each time the target service changes. As you might expect, this is quite a heavyweight approach, and it's best to code your component classes to support dynamic switching whenever possible. Unfortunately the default value is static, so you have to remember to set it to dynamic explicitly.
So, we've seen optional singular and mandatory singular, but what about multiple dependencies? There may be more than one Runnable registered in the Service Registry, and if we only bind to one of them then the choice of which one we get is arbitrary. Perhaps instead we would like to implement a "runall" command that runs
all
of the currently registered Runnables.
What would happen if we just changed the cardinality to "0..n"? In a way, that would almost work: instead of calling the
setRunnable
method just one time, DS will call
setRunnable
once for each instance of Runnable in the registry. The problem is that the class we wrote will get confused. Instead of setting a single Runnable field, we need to accumulate the Runnables into a collection. Here's the slightly modified version of the class, which you can again copy and paste directly into the
src
folder of your project:
This declaration essentially the same as before, except we have renamed the bind and unbind methods, and changed the cardinality to "0..n". As an exercise, try registering a few additional Runnable services and check that the "runall" command executes all of them. Next, what do you think will happen if we change the cardinality to "1..n"? Try verifying it does what you expect.
That's all for this lesson. Remember that the
OSGi Alliance Community Event
is happening next week in Munich, Germany, and I believe it's still not too late to
register
. See you there!
Re: Getting Started with OSGi: Declarative Services and Dependencies
Very nice article! You really help people to start using OSGi.
One comment, many people are using bnd (http://www.aQute.biz/Code/Bnd) in maven, ant, or stand alone. Bnd has a special syntax for declarative services. Instead of using a separate xml file, you can encode most cases easily in the manifest with the Service-Component header, bnd will expand this syntax into the xml file and refer to it. For example:
This allows you to keep all the information in a single file. The default for this header is mandatory static, which is very useful for services like Log Service, Configuration Admin service, etc.
Re: Getting Started with OSGi: Declarative Services and Dependencies
I couldnīt run this example with the instructions from the previous article....
I followed this steps to run it under 3.2.2:
1. File | New | Project | plug-in project.
2. Fill Project Name.
3. For the Tarjet Platform select Eclipse Versin 3.2
4. Click Next
5. Clear "Generate Activator ..."
6. Check "This plug-in will make contributions to the UI"
7. Click Finish
This was the only combination that worked, I do not know why... but I noted that the difference is in the maninfest.mf, specifically in :
Re: Getting Started with OSGi: Declarative Services and Dependencies
Hi, I've been following this series with keen interest and I've put it on the required reading list here.
Not sure if you're going to cover exactly this question in a later article but since I can't find a definite answer anywhere else I have to ask:
Is it necessary for bundles containing declared services to be started or can declarative services bootstrap a service from a bundle in the installed & resolved state?
In a standalone RCP application if new bundles are added through the update mechanism they get resolved by the update configurator but don't get started and so it seems that the services can never be found.
The solutions seem to be either add to osgi.bundles in config.ini and do a complete -clean or write code to somehow recongnise and start bundles containing services? I feel sure there must be a better way?
Hi
I dont know if anyone else ran into this odd problem. But whenever I declare an interface as a service AND provide the service listener (reference tag), the service will be provided correctly but the bind and unbind methods are not executed at all. If I comment the <service> - tag out, it works fine.
Re: Getting Started with OSGi: Declarative Services and Dependencies
Did you find an answer to your question? Even I would like to find a better way to automatically start the plug-ins. I use a command line utility to make use of services and it is rather bad that I have to go update my config.ini file ever time I have a new plug-in to be added.
Re: Getting Started with OSGi: Declarative Services and Dependencies
As long as DS is installed and started, and you have Bundle-ActivationPolicy: lazy (3.3) or Eclipse-LazyStart: true (3.2), then the other service-providing bundles don't need to be explicitly started; they can come up themselves.
Re: Getting Started with OSGi: Declarative Services and Dependencies
As far as I can tell from the docs and by experimentation, lazy-start will only activate the bundle when a class from the bundle is loaded. If you never do this the bundle is never started and your declarative services never appear.
For our purposes we wrote some code that would iterate over all installed bundles (previously installed by the eclipse configurator bundle) looking for DS config or activators referenced in their manifest and starting them where necessary.
Re: Getting Started with OSGi: Declarative Services and Dependencies
Mike, I think you are right: Even with Bundle-ActivationPolicy turned on activation only occours when loading the first class from that bundle.
I have got another question: How can I access a component (instance) from a class in the declaring bundle. Is there something like ServiceComponentRegistry.getComponent(String name) or so?
I had the same "problem", I've been working on it today and I finally I understand why it doesn't work. Actually it isn't a problem, it's perfectly correct and it's working as intended.
"If a delayed component configuration is satisfied, SCR must register the component configuration as a service in the service registry
but the activation of the component configuration is delayed until the registered service is requested
."
-- Quotation from the OSGi specifications: OSGi Service Platform Service Compendium, p. 285 (http://www2.osgi.org/Specifications/HomePage)
In other words, something else (a client) must use your service, otherwise your component will never be activated (instantiated).
If you want to know exactly what a
delayed component
is, read the specifications, but basically, if your component specifies a service, then it's a delayed one. It's possible to change that in the XML description, but I haven't tried it (look for
immediate component
).
I know your post is 2 months old, but it might help someone else.
True I believe it is all working correctly. But the specific issue I had was that, delayed activation or not, the declaration xml doesn't get read and the service (or service proxy) doesn't get registered until the bundle is started. No registration, nothing can use the service, service doesn't get activated. Catch-22.
Programmatically starting all bundles with declarative services in their manifest bootstraps the services and they start working.
I seem to have a problem. The "run" command we added to the OSGi console is not recognized in my case. After I run the application, I can see my bundles with services command:
{java.lang.Runnable}={component.name=samplerunnable, component.id=1, service.id=22}
Registered by bundle: initial@reference:file:../../Users/adilek/workspace/Tutorial/SampleExporter/ [2]
No bundles using service.
{org.eclipse.osgi.framework.console.CommandProvider}={component.name=commandprovider1, component.id=2, service.id=23}
Registered by bundle: initial@reference:file:../../Users/adilek/workspace/Tutorial/SampleImporter/ [8]
No bundles using service.
However when I use "run", the console does not seem to recognize it? It can be hard to know what the problem is with what I wrote here, but I did not modify any code provided here and followed the steps without any mistake this time hopefully. Any ideas?
Re: Getting Started with OSGi: Declarative Services and Dependencies
Great article. The only criticism I have pertains to your liberal use of synchronization blocks and your disparagement of the 'static' policy as being more 'heavyweight' than the 'dynamic' policy. In an effort to support the dynamic starting and stopping of referenced services, you have completely hamstrung your main service by introducing these synchronize blocks. Any client wishing to avail itself of this service must now obtain a mutex and wait in line like a Soviet proletarian.
If you are building a service that will never be accessed simultaneously by a large number clients, what you have done is OK, but if you are building for massive concurrency, this is absolutely unacceptable. In such a case, unless you expect the referenced service to come and go like a two-collar stree bum, the synchronized blocks are an absolute no-no, which I assume means you will have to switch the policy to 'static'. Am I missing something here?
Re: Getting Started with OSGi: Declarative Services and Dependencies
I'm posting this again, because the original contained a few minor typos, because I'm a real stickler about such things, and because I was not able to edit the original successfully:
Great article. The only criticism I have pertains to your liberal use of synchronization blocks and your disparagement of the 'static' policy as being more 'heavyweight' than the 'dynamic' policy. In an effort to support the dynamic starting and stopping of referenced services, you have completely hamstrung your main service by introducing these synchronize blocks. Any client wishing to avail itself of this service must now obtain a mutex and wait in line like a Soviet proletarian.
If you are building a service that will never be accessed simultaneously by a large number clients, what you have done is OK, but if you are building for massive concurrency, this is absolutely unacceptable. In such a case, unless you expect the referenced service to come and go like a street bum, the synchronized blocks are an absolute no-no, which I assume means you will have to switch the policy to 'static'. Am I missing something here?
Re: Getting Started with OSGi: Declarative Services and Dependencies
NOTE: In thinking about this problem over the weekend, I concluded that the best way to solve it would be to leave the policy as 'dynamic', and use a ReentrantReadWriteLock within the component implementation class. Thus, instead of synchronization blocks, I would grab a write lock when executing the code within the bind and unbind methods, and grab a read lock when executing code in the other public service methods. This allows for the public service methods to be called concurrently from multiple clients while still guarding against race conditions that may arise due to invocations of the bind/unbind methods. Any thoughts? How do others deal with these concurrency problems?
Getting Started with OSGi: Declarative Services and Dependencies
At 4:34 PM on Jun 20, 2007, Neil Bartlett
wrote:
Last time we took our first look at Declarative Services. This time we will look at the service consumer side of Declarative Services. Remember that previously we registered a service under the
java.lang.Runnableinterface; now we will create a component that depends on that service.As discussed, the Declarative Services specification is all about letting you focus on the application logic of your code, rather than the OSGi "glue" code that had to be written in previous lessons. With that in mind, we're simply going to dive into the code, but before we do that we need to create a project. Follow the same steps as in the last lesson, but use the project name "SampleImporter".
Now copy the following code from your browser and paste it into the
srcfolder inside the newly created Eclipse project:package org.example.ds; import org.eclipse.osgi.framework.console.CommandInterpreter; import org.eclipse.osgi.framework.console.CommandProvider; public class SampleCommandProvider1 implements CommandProvider { private Runnable runnable; public synchronized void setRunnable(Runnable r) { runnable = r; } public synchronized void unsetRunnable(Runnable r) { runnable = null; } public synchronized void _run(CommandInterpreter ci) { if(runnable != null) { runnable.run(); } else { ci.println("Error, no Runnable available"); } } public String getHelp() { return "\trun - execute a Runnable service"; } }This class implements the
CommandProviderinterface, which is used to extend the set of commands available at the "osgi>" prompt when you run Equinox. The reason for writing aCommandProvideris that it provides a convenient way to test our code interactively. There is a more detailed discussion of command providers in Chris Aniszczyk's article on IBM developerWorks.Notice that we don't call any OSGi APIs in this class, in fact we don't even need to import anything from the
org.osgi.*packages. The service that we depend on – in this case, an instance ofjava.lang.Runnable– is provided to us through thesetRunnablemethod, and it is taken away using theunsetRunnablemethod. We can consider this a form of dependency injection .The other two methods,
getHelpand_runare the implementation methods for the command provider. Yes, "_run" is a funny name with its leading underscore, but that is just an odd feature of the Equinox console API, and nothing to do with OSGi or Declarative Services. Methods using the leading-underscore pattern become commands on the Equinox console, so by providing a method called_runwe have added a "run" command. Another thing to notice about this class is that we're being careful to ensure that the runnable field is updated and accessed in a thread-safe way. Thread safety is particularly important in OSGi since it is intrinsically multithreaded, but frankly we should always write our code to be thread-safe.As before, we have to provide an XML file containing the DS declarations to get this to work. Copy the following into
OSGI-INF/commandprovider1.xmlin your plug-in project:There's another important step which I neglected to mention last time. (Thanks to Seamus Venasse for pointing it out .) You need to edit the
build.propertiesfile in your plug-in project, and check the box next to theOSGI-INFfolder. This is necessary to ensure the folder is included when the bundle is exported using Eclipse's export wizard, or built using PDE Build.Also we need to add the following line to the bundle manifest:
This declaration has two of the same elements that we saw before, the
implementationandservicenodes. Theimplementationnode provides the name of the class which implements the component, and theservicenode tells DS to register the component as a service. In this case we are registering under theCommandProviderinterface, which is how we let the Equinox console know about the existence of our command provider.The next element called
referenceis something we haven't seen before – it declares to DS that our component has a dependency on a service. Thenameattribute is simply an arbitrary string which names the dependency (we don't need to worry yet about what this is used for) and theinterfaceattribute specifies the name of the interface we depend on. Thebindattribute is the name of a method in the implementation class that will be called by DS when a service becomes available, or in other words, when a Runnable service is registered with the Service Registry, DS will obtain a reference to the new service object and supply it to our component using the specified method. Likewise theunbindattribute is the name of a method that will be called by DS when a service we were using becomes unavailable.The
cardinalityattribute reveals the real power of DS. This attribute controls whether the dependency is optional or mandatory, and whether it is singular or multiple. The possible values are:In this example we chose optional and singular, which means our command provider can cope with the dependent service being unavailable. Looking back at the code for the
_runmethod, you can see it was necessary to do a null check to handle such a situation.Let's see what happens if we run this bundle. If you still have your SampleExporter bundle from last time, then you should see the following response when you type the "run" command at the osgi> prompt:
Great! This confirms that we have successfully imported the Runnable service that we wrote in the last lesson. Now try using the
stopcommand to turn off the SampleExporter bundle. When you type the "run" command again you should see:Which means that DS noticed the Runnable service going away, and called our
unsetRunnablemethod to let us know.Looking again at the
cardinalityattribute, what do you think will happen if we change to "1..1", i.e. switch from an optional to a mandatory dependency? Try making that change and restarting Equinox. If the SampleExporter bundle is active when we type "run" then we will see the same message as before: "Hello from SampleRunnable". However, if SampleExporter is inactive then we will see a very different error message than before. In fact, we will see Equinox's console help message, which is its standard response to an unrecognized command. This indicates that our command provider itself has been unregistered by DS! Since the component has a mandatory dependency which cannot be satisfied, DS is forced to deactivate the component and unregister any services it was providing. That in turn means that the Equinox console forgets about the "run" command.The ease with which we can make changes like this is one of the best reasons to use Declarative Services. Remember that with
ServiceTrackerwe would have had to rewrite a fairly substantial piece of code.You might be wondering about the
policyattribute, since I haven't mentioned it yet. The value of this can be either "static" or "dynamic", and it states whether the component implementation is able to cope with having services dynamically switched. If it is not, then it is necessary for DS to deactivate the component and create a new instance each time the target service changes. As you might expect, this is quite a heavyweight approach, and it's best to code your component classes to support dynamic switching whenever possible. Unfortunately the default value is static, so you have to remember to set it to dynamic explicitly.So, we've seen optional singular and mandatory singular, but what about multiple dependencies? There may be more than one Runnable registered in the Service Registry, and if we only bind to one of them then the choice of which one we get is arbitrary. Perhaps instead we would like to implement a "runall" command that runs all of the currently registered Runnables.
What would happen if we just changed the cardinality to "0..n"? In a way, that would almost work: instead of calling the
setRunnablemethod just one time, DS will callsetRunnableonce for each instance of Runnable in the registry. The problem is that the class we wrote will get confused. Instead of setting a single Runnable field, we need to accumulate the Runnables into a collection. Here's the slightly modified version of the class, which you can again copy and paste directly into thesrcfolder of your project:package org.example.ds; import java.util.*; import org.eclipse.osgi.framework.console.CommandInterpreter; import org.eclipse.osgi.framework.console.CommandProvider; public class SampleCommandProvider2 implements CommandProvider { private List<Runnable> runnables = Collections.synchronizedList(new ArrayList<Runnable>()); public void addRunnable(Runnable r) { runnables.add(r); } public void removeRunnable(Runnable r) { runnables.remove(r); } public void _runall(CommandInterpreter ci) { synchronized(runnables) { for(Runnable r : runnables) { r.run(); } } } public String getHelp() { return "\trunall - Run all registered Runnables"; } }Now create OSGI-INF/commandprovider2.xml and copy in the following contents:
... and finally add this file to the
Service-Componentheader of the manifest, so that it looks like this:This declaration essentially the same as before, except we have renamed the bind and unbind methods, and changed the cardinality to "0..n". As an exercise, try registering a few additional Runnable services and check that the "runall" command executes all of them. Next, what do you think will happen if we change the cardinality to "1..n"? Try verifying it does what you expect.
That's all for this lesson. Remember that the OSGi Alliance Community Event is happening next week in Munich, Germany, and I believe it's still not too late to register . See you there!
18 replies so far (
Post your own)
Re: Getting Started with OSGi: Declarative Services and Dependencies
Very nice article! You really help people to start using OSGi.One comment, many people are using bnd (http://www.aQute.biz/Code/Bnd) in maven, ant, or stand alone. Bnd has a special syntax for declarative services. Instead of using a separate xml file, you can encode most cases easily in the manifest with the Service-Component header, bnd will expand this syntax into the xml file and refer to it. For example:
Service-Component: org.example.ds.SampleCommandProvider1; provide:=org.eclipse.osgi.framework.console.CommandProvider; runnable=java.lang.Runnable; optional:=runnable; dynamic:=runnableThis allows you to keep all the information in a single file. The default for this header is mandatory static, which is very useful for services like Log Service, Configuration Admin service, etc.
Re: Getting Started with OSGi: Declarative Services and Dependencies
I couldnīt run this example with the instructions from the previous article....I followed this steps to run it under 3.2.2:
1. File | New | Project | plug-in project.
2. Fill Project Name.
3. For the Tarjet Platform select Eclipse Versin 3.2
4. Click Next
5. Clear "Generate Activator ..."
6. Check "This plug-in will make contributions to the UI"
7. Click Finish
This was the only combination that worked, I do not know why... but I noted that the difference is in the maninfest.mf, specifically in :
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime
I removed the dependency org.eclips.ui and it workd too. I will glad you if you explain this.
Tank you.
Re: Getting Started with OSGi: Declarative Services and Dependencies
Hi, I've been following this series with keen interest and I've put it on the required reading list here.Not sure if you're going to cover exactly this question in a later article but since I can't find a definite answer anywhere else I have to ask:
Is it necessary for bundles containing declared services to be started or can declarative services bootstrap a service from a bundle in the installed & resolved state?
In a standalone RCP application if new bundles are added through the update mechanism they get resolved by the update configurator but don't get started and so it seems that the services can never be found.
The solutions seem to be either add to osgi.bundles in config.ini and do a complete -clean or write code to somehow recongnise and start bundles containing services? I feel sure there must be a better way?
Thanks
MikeG
A Service that references wont work
HiI dont know if anyone else ran into this odd problem. But whenever I declare an interface as a service AND provide the service listener (reference tag), the service will be provided correctly but the bind and unbind methods are not executed at all. If I comment the <service> - tag out, it works fine.
<?xml version="1.0"?>
<component name="somecomponent">
<implementation class="my.package.User"/>
<!--
<service>
<provide interface="my.package.IUser"/>
</service>
-->
<reference name="whatever" interface="my.package.ICompany" bind="doSomething" unbind="undoSomething" cardinality="1..n" policy="dynamic"/> </component>
does anybody have a similar problem?
Re: Getting Started with OSGi: Declarative Services and Dependencies
Did you find an answer to your question? Even I would like to find a better way to automatically start the plug-ins. I use a command line utility to make use of services and it is rather bad that I have to go update my config.ini file ever time I have a new plug-in to be added.Re: Getting Started with OSGi: Declarative Services and Dependencies
As long as DS is installed and started, and you have Bundle-ActivationPolicy: lazy (3.3) or Eclipse-LazyStart: true (3.2), then the other service-providing bundles don't need to be explicitly started; they can come up themselves.Alex.
Re: Getting Started with OSGi: Declarative Services and Dependencies
As far as I can tell from the docs and by experimentation, lazy-start will only activate the bundle when a class from the bundle is loaded. If you never do this the bundle is never started and your declarative services never appear.For our purposes we wrote some code that would iterate over all installed bundles (previously installed by the eclipse configurator bundle) looking for DS config or activators referenced in their manifest and starting them where necessary.
Mike
Re: Getting Started with OSGi: Declarative Services and Dependencies
Mike, I think you are right: Even with Bundle-ActivationPolicy turned on activation only occours when loading the first class from that bundle.I have got another question: How can I access a component (instance) from a class in the declaring bundle. Is there something like ServiceComponentRegistry.getComponent(String name) or so?
Heiko
Re: A Service that references wont work
I had the same "problem", I've been working on it today and I finally I understand why it doesn't work. Actually it isn't a problem, it's perfectly correct and it's working as intended."If a delayed component configuration is satisfied, SCR must register the component configuration as a service in the service registry but the activation of the component configuration is delayed until the registered service is requested ." -- Quotation from the OSGi specifications: OSGi Service Platform Service Compendium, p. 285 (http://www2.osgi.org/Specifications/HomePage)
In other words, something else (a client) must use your service, otherwise your component will never be activated (instantiated).
If you want to know exactly what a delayed component is, read the specifications, but basically, if your component specifies a service, then it's a delayed one. It's possible to change that in the XML description, but I haven't tried it (look for immediate component ).
I know your post is 2 months old, but it might help someone else.
Re: A Service that references wont work
Good to see the thread is still aliveTrue I believe it is all working correctly. But the specific issue I had was that, delayed activation or not, the declaration xml doesn't get read and the service (or service proxy) doesn't get registered until the bundle is started. No registration, nothing can use the service, service doesn't get activated. Catch-22.
Programmatically starting all bundles with declarative services in their manifest bootstraps the services and they start working.
MikeG
Re: A Service that references wont work
Hi,I seem to have a problem. The "run" command we added to the OSGi console is not recognized in my case. After I run the application, I can see my bundles with services command:
{java.lang.Runnable}={component.name=samplerunnable, component.id=1, service.id=22}
Registered by bundle: initial@reference:file:../../Users/adilek/workspace/Tutorial/SampleExporter/ [2]
No bundles using service.
{org.eclipse.osgi.framework.console.CommandProvider}={component.name=commandprovider1, component.id=2, service.id=23}
Registered by bundle: initial@reference:file:../../Users/adilek/workspace/Tutorial/SampleImporter/ [8]
No bundles using service.
However when I use "run", the console does not seem to recognize it? It can be hard to know what the problem is with what I wrote here, but I did not modify any code provided here and followed the steps without any mistake this time hopefully. Any ideas?
Re: Getting Started with OSGi: Declarative Services and Dependencies
Great article. The only criticism I have pertains to your liberal use of synchronization blocks and your disparagement of the 'static' policy as being more 'heavyweight' than the 'dynamic' policy. In an effort to support the dynamic starting and stopping of referenced services, you have completely hamstrung your main service by introducing these synchronize blocks. Any client wishing to avail itself of this service must now obtain a mutex and wait in line like a Soviet proletarian.If you are building a service that will never be accessed simultaneously by a large number clients, what you have done is OK, but if you are building for massive concurrency, this is absolutely unacceptable. In such a case, unless you expect the referenced service to come and go like a two-collar stree bum, the synchronized blocks are an absolute no-no, which I assume means you will have to switch the policy to 'static'. Am I missing something here?
Re: Getting Started with OSGi: Declarative Services and Dependencies
I'm posting this again, because the original contained a few minor typos, because I'm a real stickler about such things, and because I was not able to edit the original successfully:Great article. The only criticism I have pertains to your liberal use of synchronization blocks and your disparagement of the 'static' policy as being more 'heavyweight' than the 'dynamic' policy. In an effort to support the dynamic starting and stopping of referenced services, you have completely hamstrung your main service by introducing these synchronize blocks. Any client wishing to avail itself of this service must now obtain a mutex and wait in line like a Soviet proletarian.
If you are building a service that will never be accessed simultaneously by a large number clients, what you have done is OK, but if you are building for massive concurrency, this is absolutely unacceptable. In such a case, unless you expect the referenced service to come and go like a street bum, the synchronized blocks are an absolute no-no, which I assume means you will have to switch the policy to 'static'. Am I missing something here?
Re: Getting Started with OSGi: Declarative Services and Dependencies
NOTE: In thinking about this problem over the weekend, I concluded that the best way to solve it would be to leave the policy as 'dynamic', and use a ReentrantReadWriteLock within the component implementation class. Thus, instead of synchronization blocks, I would grab a write lock when executing the code within the bind and unbind methods, and grab a read lock when executing code in the other public service methods. This allows for the public service methods to be called concurrently from multiple clients while still guarding against race conditions that may arise due to invocations of the bind/unbind methods. Any thoughts? How do others deal with these concurrency problems?