Hi Mdu
if all consumers are in separated bundles, then you can simply arrange your
service provider to implement the org.osgi.framework.ServiceFactory
interface. Hence, all consumers will be injected with a private copy of the
service provider service.
if, now you have multiple consumer components from the same bundle, and you
want each one depending on a private copy of a given service provider, then
DM4 does not directly support this.
In this case, one work around is possible and as Raymond said, you can use
prototype scopes.
However it won't be fully transparent, because the Provider has to
implement the PrototypeServiceFactory interface, and the Consumer then must
use BundleContext.getServiceObjects in order to get its own copy of the
provider dependency.
So, assuming you have a Consumer component which depends on a Provider
service; then you would basically do something like this at the consumer
activator side:
dm.add(createComponent()
.setImplementation(Consumer.class)
.add(createServiceDependency().setService(Provider.class).setCallbacks("bind",
null)));
public class Consumer {
volatile BundleContext ctx;
volatile Provider provider; // an instance copy
void bind(ServiceReference<Provider> ref) {
ServiceObjects<Provider> providers = ctx.getServiceObjects(ref);
provider = providers.getService();
}
}
There is now some ways to encapsulates the usage of ServiceObjects in a
separate helper class.
You will find an example in [1], where a "PrototypeCB" helper class is used
to proxy the injection of the Provider into the Consumer:
when the Provider is injected into the PrototypeCB proxy, then the proxy
uses the getServiceObjects API to get an instance copy, which is
then injected in the real Consumer implementation class, using a java8
method reference.
The Consumer then becomes:
public class Consumer { void bind(Provider provider) { } }
and the Consumer Activator is then using the PrototypeCB as a proxy
callback, like this:
import static prototype.consumer.PrototypeCB.prototype;
public void init(BundleContext bc, DependencyManager dm) throws Exception {
dm.add(createComponent()
.setImplementation(Consumer.class)
.add(createServiceDependency().setService(Provider.class).setCallbacks(prototype(bc,
Consumer::bind), "bind", null)));
You can take a look at the PrototypeCB from [1], in the consumer bundle.
So, in the code above, the prototype() helper function returns a
PrototypeCB helper proxy object, where the Provider dependency will be
injected first (in PrototypeCB.bind method).
Then the proxy will get an instance copy of the Provider and will inject
the copy in the Consumer::bind method reference.
Now, if you really need DM4 to internally support prototype scopes, like
DS, then please open a JIRA issue, and I will start working on it.
[1] https://github.com/pderop/dm.psf
hope this helps;
cheers;
/Pierre
On Thu, Aug 25, 2016 at 7:18 AM, David Jencks <
[email protected]> wrote:
> I’d be really amazed if this worked. I imagine that DM is quite similar
> to DS, and you definitely can’t do that in DS, you have to use the scope
> rather than trying to write your own serviceFactory or
> PrototypeServiceFactory. If your service is e.g. ServiceFactory that’s
> what you’ll get when you look up the service, not the service it’s a
> factory for. DS already registers a ServiceFactory for each component.
>
> Hopefully someone who actually knows something about DM will speak up soon
> :-)
>
> david jencks
>
> > On Aug 24, 2016, at 5:54 PM, Raymond Auge <[email protected]>
> wrote:
> >
> > I'm fairly certain that DM supports publishing services of any type and
> > doesn't care about scoping, including implementations of
> > PrototypeServiceFactory.
> >
> > Mdu, your service simply needs to implement PrototypeServiceFactory and
> you
> > should be able to use the DM's imperative API as usual.
> >
> > But any other DM experts may correct me if this is wrong.
> >
> > - Ray
> >
> > On Wed, Aug 24, 2016 at 3:13 PM, mduduzik <[email protected]>
> wrote:
> >
> >> Ray/David,
> >> Thanks for your prompt responses. I would like to accomplish this using
> >> API/Activator approach in DM4 (Felix Dependency Manager 4). Here's the
> >> context within which I would like to do this:
> >>
> >> public class Activator extends DependencyActivatorBase {
> >> @Override
> >> public void init(BundleContext ctx, DependencyManager dm) throws
> >> Exception
> >> {
> >> }
> >> }
> >>
> >> So in other words, a non-Annotation based approach. I hope my request is
> >> clearer.
> >>
> >> Regards.
> >> -Mdu
> >>
> >>
> >>
> >> --
> >> View this message in context: http://apache-felix.18485.x6.
> >> nabble.com/DM4-service-factory-multiple-service-instance-support-
> >> tp5018226p5018230.html
> >> Sent from the Apache Felix - Users mailing list archive at Nabble.com.
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: [email protected]
> >> For additional commands, e-mail: [email protected]
> >>
> >>
> >
> >
> > --
> > *Raymond Augé* <http://www.liferay.com/web/raymond.auge/profile>
> > (@rotty3000)
> > Senior Software Architect *Liferay, Inc.* <http://www.liferay.com>
> > (@Liferay)
> > Board Member & EEG Co-Chair, OSGi Alliance <http://osgi.org>
> (@OSGiAlliance)
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
>
>