Thanks Pierre and Neil for your replies!
To avoid splitting this thread, I'll also reply to Neil's email here.
I agree with Neil completely about the Blueprint lifecycle (ugly). I
much prefer the DS lifecycle management - but miss the ability in DS or
DM to manage bundle-private objects. I find it interesting that OSGi has
solved the problem of a global class namespace (via Export-Package), but
has then created a single global service namespace.
Regarding the use of "new":
(a) It would be nice to share code between OSGi and non-OSGi
environments. In non-OSGi environments, use of dependency injection
(rather than explicit use of new) is wide-spread.
Do you not have problems when trying to share code between OSGi and
non-OSGi environments?
(b) DI isn't usually used to inject things that can be created with
"new". Instead, it is predominantly used to inject singleton objects
that are used by many other objects. As an example, a common _cache_ may
be injected, or a serialization-helper. The alternative to DI in this
case is not "new", but instead the old "static singleton" pattern, or
lookup via JNDI or similar. Or to retrieve the object from the OSGi
service registry - but that leads to "polluting" of the global service
registry which I am concerned about.
Do you not have problems when sharing a "bundle-private" object between
multiple DS-managed objects?
(c) One major motivation for using DI is to support unit testing. When a
class uses DI properly, then a unit test can instantiate that class with
mocks for the various other objects it interacts with. The test can then
verify that the class under test interacts with mock objects as
expected. It can also emulate various failures in the mocked systems, eg
returning error-codes or throwing exceptions. When a class uses "new" to
instantiate a helper object, no mocking of the external class is possible.
When you use "new" in your code, does this not cause you problems with
unit test coverage?
Because of the above, I don't currently see using "new" as an
alternative to DI for wiring up objects inside a bundle.
Pierre, many thanks for your very detailed reply.
Re link to iPojo - that's next on my list of things to investigate; I've
been using spring-dm, blueprint and felix-dm up to now but haven't yet
taken time to investigate ipojo. And thanks for link [1] - Christian
Schneider is asking exactly the same question as I am, in Feb 2014.
Sadly Felix Meshberger's reply is clear : not supported in DS. I don't
yet understand why some people think this is important (Christian,
myself for example) while others don't. See
https://mail.osgi.org/pipermail/osgi-dev/2014-February/004295.html and
the followup emails.
The Felix-DM CompositionManager example you linked to looks very
interesting, thanks. Unfortunately javadoc for
"Component.setComposition" is pretty unhelpful. As far as I can tell,
the "composition" feature allows a developer to define in DM:
* a single Component
* with all the dependencies that need to be injected into it
except that
* instead of DM instantiating a single object when the dependencies are
met, it invokes a factory method that returns a collection of objects, and
* instead of injection of these dependencies being performed on a single
object, it is performed on the collection of objects
Have I understood? If so, that is interesting but not AFAICT what I am
looking for.
While searching for info on "composition", I came across
http://de.slideshare.net/mfrancis/the-ultimate-dependency-manager-shoot-out-x-uiterlinden-s-mak
. In particular, slide 19 talks about support in ipojo for "intra-bundle
mechanism" and "scoped service registry" which look exactly like what I
am missing in DS. Sadly, the topic isn't mentioned again in the
slideshow. However searching for those terms led me to this page:
*
http://felix.apache.org/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-gettingstarted/ipojo-composition-tutorial.html
And this section from the ipojo "composition" documentation (which
appears to be not related to the felix-dm composition feature) is
exactly what I think is missing from DS/DM:
> OSGi defines only one service registry, accessible by any bundles.
iPOJO splits these two interaction types. Instances receive an iPOJO Bundle
> Context delegating bundle-related methods to the "regular" bundle
context, and service-related methods to a service context. This service
context
> can access to the OSGi service registry or to a new one. Each
composition instances have a service registry.
I'm not so concerned about "too many services in the registry" as I am
about *bundle-private* services being present in the global registry.
Do you see any reason why DM and DS could not adopt the same approach as
iPojo, ie a per-composition (or at least per-bundle) service registry? I
could imagine the following enhancement for DS:
<component>
<service>
<provide interface="..." scope="local"/>
where the new "scope" attribute indicates that this particular component
should be placed into the per-bundle service registry rather than the
global one. All <reference> elements would then look first in the
per-bundle registry before looking in the global one.
For DM, something similar could be done with:
createComponent().setInterface("..", Scope.LOCAL)
Maybe another solution is to take advantage of felix-dm's ability to
define "dependency handlers", and add another kind of dependency called
"local" or similar? [as suggested by Karl Pauls in the email pointed out
by Pierre]
All opinions gratefully accepted!
Regards, Simon
On 05/22/2015 08:34 AM, Pierre De Rop wrote:
Hello Simon,
DM, like DS does not implement a private service registry to intra-bundle
components (well, except for optimized DM filter indices, but this is
another story).
I think Ipojo do support what you are describing, but I prefer to let other
people respond about this since I'm not enough experienced in iPojo. See
[1] about this, which comes from the osgi mailing list.
Now, I tend to agree with Neil, and intra-bundle private services can
simply be instantiated with the "new" keyword.
Alternatively, with DM, you can also use a composition of service
components: this allows you to:
- only register one single service for the bundle in the OSGi service
registry (or even only one DM component if it does not provide any services
at all, but just needs to define some dependencies to external services
(outside the bundle).
- and define a composition of objects that will get injected with the
external services.
For example, you can take a look at [2] for a concrete sample code of a
bundle which defines a component that is instantiated using a
"CompositionManager" pojo that is first injected with a configuration. And
from the configuration, the pojo may then create an implementation for the
service that the bundle provides, and also, some other pojo objects that
are part of the service implementation. The pojos will then be injected
with all the external service dependencies defined in the Activator (either
using field injection of bind method callbacks).
There is also another example which does not use a Factory, but only a
service composition in [3].
Finally, I would like to say that it's a not a real problem to have many
services registered in the Osgi service registry.
Registering services is cheap. And DM now supports an actor based thread
model which allows to activate, manage, and bind service components
concurrently, using a shared threadpool, and there is no startup time
degradation (I often start around 20000 services and my Felix Framework
starts in few of seconds). The new thread model is descriped in [4].
Also, regarding service diagnostics, even if you have thousands of micro
services registered in the OSGi registry, then DM gogo shell supports
advanced commands that allows you to quickly make some diagnostics (like
loop detection, missing service root causes, service lookup using filters,
etc ...).
[1] https://mail.osgi.org/pipermail/osgi-dev/2014-February/004310.html
[2]
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/compositefactory/
[3]
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/composite/
[4]
http://felix.apache.org/documentation/subprojects/apache-felix-dependency-manager/reference/thread-model.html
kind regards;
/Pierre
On Thu, May 21, 2015 at 4:52 PM, Simon Kitching <[email protected]> wrote:
Hi,
In blueprint it is possible to define arbitrary objects (beans) which are
not published to the service registry but nevertheless can be injected into
other beans.
AFAICT, in both declarative-services and felix-dm, the only objects that
can be injected are references to services from the OSGi registry. Is this
correct?
I understand that with DS and DM, components follow the standard OSGi
lifecycles, in contrast to the Blueprint approach of "hiding" the
lifecycle. In particular, in DS and DM when a component's mandatory
dependency is deregistered then the component is also deregistered (which
can cascade further). And the kind of tracking of dependencies required to
make this happen is exactly what a service registry does.
However it's common for a bundle to have objects which are purely internal
implementation details of the bundle, and are not for external use. Yet as
far as I can see, in order to manage them with DS or DM, such internal
objects need to be published into the global service registry - just to be
able to then inject them back into components in the same bundle.
Have I misunderstood something?
Thanks,
Simon
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]