karaf-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Kevin Schmidt <ktschm...@gmail.com>
Subject Re: Class resolved/found on Karaf start but not on bundle restart
Date Mon, 04 Sep 2017 15:13:09 GMT

Thanks for the catch.  I'm dealing with some third party libs that aren't
OSGi bundles and having to do stuff with declaring things optional and this
one slipped into the mix.

I was not aware the framework could not wire the package when resolving the
bundle even if the package is present and exported.  It is also confusing
that the framework reports it has been resolved.  That reporting resolved
when not isn't a bug?  This is what was confusing.

And yes, it really is the optional service I care about.

Thanks for the link to the talk as well.  A good refresher.


On Mon, Sep 4, 2017 at 1:51 AM, Timothy Ward <tim.ward@paremus.com> wrote:

> Hi Kevin,
> This problem occurs because you have incorrectly marked the import for the
> “com.foo.interfaces” package as “resolution:=optional”. This package is
> *not* optional as a type from it is is injected into your blueprint bean
> which in turn means that the type must be loadable for your bundle to start.
> When you mark a package import as optional then the OSGi framework is at
> liberty to not wire this package when resolving your bundle. In this case
> the refresh operation is either making the package that you want
> unavailable, or incompatible with the rest of your class space. Either way
> optional package imports are very difficult to do correctly, and usually
> require you to segregate a whole code path. You must then load this code
> path defensively using a try/catch ClassNotFoundException and be prepared
> for it not to exist.
> Note that optional services are much easier to deal with than optional
> packages. In your case it will simply result in an empty reference list.
> See also, this talk on optionality in OSGi that I gave several years ago
> <https://www.slideshare.net/mfrancis/when-is-optional-really-optional-tim-ward>.
> Sadly blueprint 1.1 never really happened as nobody was sufficiently
> interested in updating the standard.
> Regards,
> Tim Ward
> On 1 Sep 2017r , at 23:26, Kevin Schmidt <ktschmidt@gmail.com> wrote:
> Hi,
> I have a strange problem with class resolution that is befuddling me.
> I have a bundle A that uses services from other bundles B and C that
> implement an interface I.  Bundle A also uses classes from bundle D.  I am
> using blueprint for bundle A and have a reference-list defined as such:
> <reference-list id="svcs" interface="com.foo.interfaces.I"
> member-type="service-object" availability="optional"/>
> And this is injected into a bean instantiated from a class found in bundle
> D, the bean itself registered as a service.
> When I start Karaf (4.1.1) all bundles start just fine and everything
> works.  The services implementing interface I from bundles B and C are all
> in the reference-list as expected.  And I am able to restart bundle A and
> everything comes back up fine.
> However, if I do something as simple as refreshing bundle D, bundle A
> fails to start indicating a ClassNotFoundException for interface I.
> Specifically:
> Unable to start blueprint container for bundle com.foo.a.service/10.0.0.
> org.osgi.service.blueprint.container.ComponentDefinitionException:
> org.osgi.service.blueprint.container.ComponentDefinitionException: Unable
> to load class com.foo.a.Service from recipe BeanRecipe[name='serviceA']
> at org.apache.aries.blueprint.container.ServiceRecipe.
> createService(ServiceRecipe.java:310)[23:org.apache.aries.
> blueprint.core:1.8.0]
> ...
> Caused by: java.lang.ClassNotFoundException: com.foo.interfaces.I not
> found by com.foo.a.service [401]
> at org.apache.felix.framework.BundleWiringImpl.
> findClassOrResourceByDelegation(BundleWiringImpl.java:1550)[
> org.apache.felix.framework-5.6.2.jar:]
> at org.apache.felix.framework.BundleWiringImpl.access$200(
> BundleWiringImpl.java:79)[org.apache.felix.framework-5.6.2.jar:]
> at org.apache.felix.framework.BundleWiringImpl$
> BundleClassLoader.loadClass(BundleWiringImpl.java:1958)[
> org.apache.felix.framework-5.6.2.jar:]
> at java.lang.ClassLoader.loadClass(ClassLoader.java:357)[:1.8.0_77]
> at org.apache.felix.framework.Felix.loadBundleClass(Felix.
> java:1925)[org.apache.felix.framework-5.6.2.jar:]
> at org.apache.felix.framework.BundleImpl.loadClass(
> BundleImpl.java:978)[org.apache.felix.framework-5.6.2.jar:]
> at org.apache.aries.blueprint.container.BlueprintContainerImpl.loadClass(
> BlueprintContainerImpl.java:468)[23:org.apache.aries.blueprint.core:1.8.0]
> at org.apache.aries.blueprint.container.GenericType.parse(
> GenericType.java:137)[23:org.apache.aries.blueprint.core:1.8.0]
> at org.apache.aries.blueprint.container.AbstractServiceReferenceRecipe
> .loadType(AbstractServiceReferenceRecipe.java:307)[23:org.apache.
> aries.blueprint.core:1.8.0]
> However, if I look at the headers for bundle A (#401), it shows the import
> of the package interface I is in is resolved, e.g. the following line in
> the imports is in black:
> com.foo.interfaces;resolution:=optional,
> If the headers indicates the import is resolved ok, and at Karaf startup
> that import found the interface I, why would it fail when bundle D is
> refreshed?
> Yes, I'm aware that if com.foo.interfaces was exported from another bundle
> that could cause problems, and I'm double checking everything to make sure
> that isn't the case, but I don't think there is another export of it.
> How can I diagnose what where bundle A has resolved that import from and
> why it thinks interface I cannot be found?  bundle:diag just reports the
> same stack trace I showed above.
> Using an earlier install of more of less the same bundles (but not
> completely identical, so yes, that is a variable) in Karaf 3.0.6,
> everything works fine.  I can restart bundle A and refresh bundle D and
> bundle A finds the interface I and starts fine.  Did something change with
> Karaf 4 or the blueprint used by it?
> Thanks,
> Kevin

View raw message