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