Hey All,
I managed to find a relatively elegant solution to this with pure DS.

Given a component using an optional/dynamic package(s):

import com.liferay.demo.foo.Foo; // The optional package
@Component(
    enabled = false // disable so that DS ignores it
)
public class OptionalPackageConsumer implements Foo {...}

A controller is created which does the classloader check:

@Component
public class OptionalPackageConsumerStarter {
   @Activate
    void activate(ComponentContext componentContext) {
        try {
            Class.forName(com.liferay.demo.foo.Foo.class.getName());


componentContext.enableComponent(OptionalPackageConsumer.class.getName());
        }
        catch (Throwable t) {
            _log.warn("Could not find {}", t.getMessage());
        }
    }
}

If successful, the component is enabled, otherwise, don't!

- Ray



On Thu, Apr 27, 2017 at 1:48 AM, Fauth Dirk (AA-AS/EIS2-EU) <
dirk.fa...@de.bosch.com> wrote:

> I totally agree that a clean solution would be to extract the service in
> another bundle with a non optional dependency, as this avoids any runtime
> issues at the beginning by not starting the bundle. Will think about that
> for the Platform Runtime after Oxygen, as such a change is not allowed at
> the current state of the development.
>
>
>
> Nevertheless I created https://bugs.eclipse.org/bugs/
> show_bug.cgi?id=515873 because the NPE is misleading. Whether an
> exception should be shown or not is discussable. Felix is not showing
> anything at all, which also makes it hard to find the reason why the
> service is not activated. Therefore logging the exception is perfectly fine
> in my opinion. But the NPE when using the field strategy looks incorrect to
> me. It doesn’t help anyway to find the real cause.
>
>
>
> Mit freundlichen Grüßen / Best regards
>
>
> *Dirk Fauth *
> Automotive Service Solutions, ESI application (AA-AS/EIS2-EU)
> Robert Bosch GmbH | Postfach 11 29 | 73201 Plochingen | GERMANY |
> www.bosch.com
> Tel. +49(7153)666-1155 <+49%207153%206661155> | dirk.fa...@de.bosch.com
>
> Sitz: Stuttgart, Registergericht: Amtsgericht Stuttgart, HRB 14000;
> Aufsichtsratsvorsitzender: Franz Fehrenbach; Geschäftsführung: Dr. Volkmar
> Denner,
> Prof. Dr. Stefan Asenkerschbaumer, Dr. Rolf Bulander, Dr. Stefan Hartung,
> Dr. Markus Heyn, Dr. Dirk Hoheisel,
> Christoph Kübel, Uwe Raschke, Peter Tyroller
>
>
> *Von:* osgi-dev-boun...@mail.osgi.org [mailto:osgi-dev-bounces@mail.
> osgi.org] *Im Auftrag von *Thomas Watson
> *Gesendet:* Mittwoch, 26. April 2017 14:38
> *An:* osgi-dev@mail.osgi.org
>
> *Betreff:* Re: [osgi-dev] handling optional/dynamic imports in DS
>
>
>
> By Private-Package Peter means he packages the optional package internally
> in the bundle but also optionally imports it so that if it is resolved to
> an external provider then that will be used over the internal copy.  The
> Private-Package header in bnd will instruct bnd to package the package
> internally in the jar.
>
>
>
> Personally, if I had this scenario I would extract the service component
> out to a new bundle that has a non-optional import for the package and be
> done with the magic of dynamic or optional imports.  Or if that is not what
> you want I would make it a fragment the that has a non-optional import.
> That way the bundle with the service component cannot possibly provide its
> service component until it is resolved.
>
>
>
> I'm not sure I follow your example that is failing in equinox, but open a
> bug if you find it is an Equinox bug.
>
>
> Tom
>
>
>
>
>
>
> ----- Original message -----
> From: "Fauth Dirk (AA-AS/EIS2-EU)" <dirk.fa...@de.bosch.com>
> Sent by: osgi-dev-boun...@mail.osgi.org
> To: OSGi Developer Mail List <osgi-dev@mail.osgi.org>
> Cc:
> Subject: Re: [osgi-dev] handling optional/dynamic imports in DS
> Date: Wed, Apr 26, 2017 3:02 AM
>
>
> Interestingly this works fine when running from Bndtools with Felix.
>
>
>
> If I try the same with Equinox for projects created with PDE I get a
> NullPointerException. IIRC Private-Package is something special to Bnd. Is
> that correct? I wonder if that exception is caused by some PDE flaws or if
> it is an issue in Equinox Oxygen. In both cases Apache Felix SCR 2.0 is
> used. (in Oxygen 2.0.8 and in Bndtools 2.0.2)
>
>
>
> *org.osgi.framework.ServiceException*: Exception in
> org.apache.felix.scr.impl.manager.SingleComponentManager.getService()
>
>        at org.eclipse.osgi.internal.serviceregistry.ServiceFactoryUse.
> factoryGetService(*ServiceFactoryUse.java:222*)
>
>        at org.eclipse.osgi.internal.serviceregistry.
> ServiceFactoryUse.getService(*ServiceFactoryUse.java:111*)
>
>        at org.eclipse.osgi.internal.serviceregistry.
> ServiceConsumer$2.getService(*ServiceConsumer.java:45*)
>
>        at org.eclipse.osgi.internal.serviceregistry.
> ServiceRegistrationImpl.getService(*ServiceRegistrationImpl.java:508*)
>
>        at org.eclipse.osgi.internal.serviceregistry.
> ServiceRegistry.getService(*ServiceRegistry.java:461*)
>
>        at org.eclipse.osgi.internal.framework.BundleContextImpl.
> getService(*BundleContextImpl.java:624*)
>
>        at org.apache.felix.scr.impl.manager.SingleRefPair.
> getServiceObject(*SingleRefPair.java:72*)
>
>        at org.apache.felix.scr.impl.inject.FieldHandler$
> ReferenceMethodImpl.getServiceObject(*FieldHandler.java:985*)
>
>        at org.apache.felix.scr.impl.manager.DependencyManager.
> getServiceObject(*DependencyManager.java:2201*)
>
>        at org.apache.felix.scr.impl.manager.DependencyManager$
> MultipleStaticReluctantCustomizer.prebind(*DependencyManager.java:699*)
>
>        at org.apache.felix.scr.impl.manager.DependencyManager.prebind(
> *DependencyManager.java:1520*)
>
>        at org.apache.felix.scr.impl.manager.AbstractComponentManager.
> collectDependencies(*AbstractComponentManager.java:1006*)
>
>        at org.apache.felix.scr.impl.manager.SingleComponentManager.
> getServiceInternal(*SingleComponentManager.java:859*)
>
>        at org.apache.felix.scr.impl.manager.SingleComponentManager.
> getService(*SingleComponentManager.java:823*)
>
>        at org.eclipse.osgi.internal.serviceregistry.
> ServiceFactoryUse$1.run(*ServiceFactoryUse.java:212*)
>
>        at java.security.AccessController.doPrivileged(*Native Method*)
>
>        at org.eclipse.osgi.internal.serviceregistry.ServiceFactoryUse.
> factoryGetService(*ServiceFactoryUse.java:210*)
>
>        at org.eclipse.osgi.internal.serviceregistry.
> ServiceFactoryUse.getService(*ServiceFactoryUse.java:111*)
>
>        at org.eclipse.osgi.internal.serviceregistry.
> ServiceConsumer$2.getService(*ServiceConsumer.java:45*)
>
>        at org.eclipse.osgi.internal.serviceregistry.
> ServiceRegistrationImpl.getService(*ServiceRegistrationImpl.java:508*)
>
>        at org.eclipse.osgi.internal.serviceregistry.
> ServiceRegistry.getService(*ServiceRegistry.java:461*)
>
>        at org.eclipse.osgi.internal.framework.BundleContextImpl.
> getService(*BundleContextImpl.java:624*)
>
>        at org.apache.felix.gogo.runtime.CommandProxy.getTarget(
> *CommandProxy.java:50*)
>
>        at org.apache.felix.gogo.runtime.CommandProxy.execute(
> *CommandProxy.java:72*)
>
>        at org.apache.felix.gogo.runtime.Closure.executeCmd(
> *Closure.java:477*)
>
>        at org.apache.felix.gogo.runtime.Closure.executeStatement(
> *Closure.java:403*)
>
>        at org.apache.felix.gogo.runtime.Pipe.run(*Pipe.java:108*)
>
>        at org.apache.felix.gogo.runtime.Closure.execute(*Closure.java:183*
> )
>
>        at org.apache.felix.gogo.runtime.Closure.execute(*Closure.java:120*
> )
>
>        at org.apache.felix.gogo.runtime.CommandSessionImpl.execute(
> *CommandSessionImpl.java:89*)
>
>        at org.apache.felix.gogo.shell.Console.run(*Console.java:62*)
>
>        at org.apache.felix.gogo.shell.Shell.console(*Shell.java:203*)
>
>        at org.apache.felix.gogo.shell.Shell.gosh(*Shell.java:128*)
>
>        at sun.reflect.NativeMethodAccessorImpl.invoke0(*Native Method*)
>
>        at sun.reflect.NativeMethodAccessorImpl.invoke(
> *NativeMethodAccessorImpl.java:62*)
>
>        at sun.reflect.DelegatingMethodAccessorImpl.invoke(
> *DelegatingMethodAccessorImpl.java:43*)
>
>        at java.lang.reflect.Method.invoke(*Method.java:498*)
>
>        at org.apache.felix.gogo.runtime.Reflective.invoke(
> *Reflective.java:137*)
>
>        at org.apache.felix.gogo.runtime.CommandProxy.execute(
> *CommandProxy.java:82*)
>
>        at org.apache.felix.gogo.runtime.Closure.executeCmd(
> *Closure.java:477*)
>
>        at org.apache.felix.gogo.runtime.Closure.executeStatement(
> *Closure.java:403*)
>
>        at org.apache.felix.gogo.runtime.Pipe.run(*Pipe.java:108*)
>
>        at org.apache.felix.gogo.runtime.Closure.execute(*Closure.java:183*
> )
>
>        at org.apache.felix.gogo.runtime.Closure.execute(*Closure.java:120*
> )
>
>        at org.apache.felix.gogo.runtime.CommandSessionImpl.execute(
> *CommandSessionImpl.java:89*)
>
>        at org.apache.felix.gogo.shell.Activator.run(*Activator.java:75*)
>
>        at java.lang.Thread.run(*Thread.java:745*)
>
> Caused by: *java.lang.NullPointerException*
>
>        at org.apache.felix.scr.impl.inject.FieldHandler.validateField(
> *FieldHandler.java:279*)
>
>        at org.apache.felix.scr.impl.inject.FieldHandler.access$500(
> *FieldHandler.java:51*)
>
>        at org.apache.felix.scr.impl.inject.FieldHandler$
> NotResolved.resolve(*FieldHandler.java:839*)
>
>        at org.apache.felix.scr.impl.inject.FieldHandler$
> NotResolved.fieldExists(*FieldHandler.java:864*)
>
>        at org.apache.felix.scr.impl.inject.FieldHandler.fieldExists(
> *FieldHandler.java:918*)
>
>        at org.apache.felix.scr.impl.inject.FieldHandler$3.init(
> *FieldHandler.java:1018*)
>
>        at org.apache.felix.scr.impl.manager.DependencyManager.
> invokeInitMethod(*DependencyManager.java:1657*)
>
>        at org.apache.felix.scr.impl.manager.DependencyManager.open(
> *DependencyManager.java:1533*)
>
>        at org.apache.felix.scr.impl.manager.SingleComponentManager.
> createImplementationObject(*SingleComponentManager.java:261*)
>
>        at org.apache.felix.scr.impl.manager.SingleComponentManager.
> createComponent(*SingleComponentManager.java:109*)
>
>        at org.apache.felix.scr.impl.manager.SingleComponentManager.
> getService(*SingleComponentManager.java:906*)
>
>        at org.apache.felix.scr.impl.manager.SingleComponentManager.
> getServiceInternal(*SingleComponentManager.java:879*)
>
>        at org.apache.felix.scr.impl.manager.SingleComponentManager.
> getService(*SingleComponentManager.java:823*)
>
>        at org.eclipse.osgi.internal.serviceregistry.
> ServiceFactoryUse$1.run(*ServiceFactoryUse.java:212*)
>
>        at java.security.AccessController.doPrivileged(*Native Method*)
>
>        at org.eclipse.osgi.internal.serviceregistry.ServiceFactoryUse.
> factoryGetService(*ServiceFactoryUse.java:210*)
>
>        ... 46 more
>
>
>
> Mit freundlichen Grüßen / Best regards
>
> *Dirk Fauth*
>
> Automotive Service Solutions, ESI application (AA-AS/EIS2-EU)
> Robert Bosch GmbH | Postfach 11 29 | 73201 Plochingen | GERMANY |
> www.bosch.com
> Tel. +49(7153)666-1155 <+49%207153%206661155> | dirk.fa...@de.bosch.com
>
> Sitz: Stuttgart, Registergericht: Amtsgericht Stuttgart, HRB 14000;
> Aufsichtsratsvorsitzender: Franz Fehrenbach; Geschäftsführung: Dr. Volkmar
> Denner,
> Prof. Dr. Stefan Asenkerschbaumer, Dr. Rolf Bulander, Dr. Stefan Hartung,
> Dr. Markus Heyn, Dr. Dirk Hoheisel,
> Christoph Kübel, Uwe Raschke, Peter Tyroller
>
> *Von:* osgi-dev-boun...@mail.osgi.org [mailto:osgi-dev-bounces@mail.
> osgi.org <osgi-dev-boun...@mail.osgi.org>] *Im Auftrag von *Peter Kriens
> *Gesendet:* Mittwoch, 26. April 2017 09:14
> *An:* OSGi Developer Mail List <osgi-dev@mail.osgi.org>
> *Betreff:* Re: [osgi-dev] handling optional/dynamic imports in DS
>
>
>
> I used to import the package optional and then provide it as an internal
> Private-Package. The import has priority but the internal package is used
> when the import fails to resolve. Since you’re then always wired to a
> package you can handle dependencies on the place they should be handled:
> services.
>
>
>
> This keeps everybody happy internally for very little cost. I’ve included
> a bndtools/enRoute example.
>
>
>
> Kind regards,
>
>
>
>             Peter Kriens
>
>
>
>
>
> ————————————————— bnd.bnd
>
> Private-Package: \
>
>                 org.osgi.service.cm,\
>
>                 com.foo.provider
>
>
>
> Import-Package: \
>
>                 org.osgi.service.cm;resolution:=optional,\
>
>                 *
>
>
>
> -buildpath: \
>
>                 osgi.enroute.base.api
>
> -runrequires: \
>
>                 osgi.identity;filter:='(osgi.identity=com.foo.provider)',\
>
>                 osgi.identity;filter:='(osgi.identity=org.apache.felix.
> gogo.runtime)',\
>
>                 osgi.identity;filter:='(osgi.identity=org.apache.felix.
> gogo.shell)',\
>
>                 osgi.identity;filter:='(osgi.identity=org.apache.felix.
> gogo.command)'
>
> -runbundles: \
>
>                 com.foo.provider;version=snapshot,\
>
>                 org.apache.felix.log;version='[1.0.1,1.0.2)',\
>
>                 org.apache.felix.scr;version='[2.0.2,2.0.3)',\
>
>                 org.apache.felix.gogo.runtime,\
>
>                 org.apache.felix.gogo.shell;version=0.16
>
>
>
> ————————————————— com.foo.provider.Optional
>
> @Component
>
> public class Optional
>
> {
>
>    @Reference(cardinality=ReferenceCardinality.OPTIONAL)
>
>    ConfigurationAdmin admin;
>
>
>
>    @Activate
>
>    void activate() {
>
>       System.out.println("activate " + admin);
>
>    }
>
> }
>
>
>
> On 25 Apr 2017, at 23:10, Raymond Auge <raymond.a...@liferay.com> wrote:
>
>
>
> I'm wondering if there is a reasonable model for handling optional or
> dynamic package imports in DS.
>
> While optionality at the package level is not an ideal model, sometimes it
> can't be avoided.
>
> I'd like to know if others have come across a "reasonable" way to model
> this in DS.
>
>
>
> Sincerely,
>
> --
>
> *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)
>
> _______________________________________________
> OSGi Developer Mail List
> osgi-dev@mail.osgi.org
> https://mail.osgi.org/mailman/listinfo/osgi-dev
>
>
>
> _______________________________________________
> OSGi Developer Mail List
> osgi-dev@mail.osgi.org
> https://mail.osgi.org/mailman/listinfo/osgi-dev
>
>
>
>
>
> _______________________________________________
> OSGi Developer Mail List
> osgi-dev@mail.osgi.org
> https://mail.osgi.org/mailman/listinfo/osgi-dev
>



-- 
*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)
_______________________________________________
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Reply via email to