felix-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Thomas Watson (JIRA)" <j...@apache.org>
Subject [jira] [Comment Edited] (FELIX-5389) NullPointerException in Candidates#prepare() method
Date Wed, 02 Nov 2016 19:51:58 GMT

    [ https://issues.apache.org/jira/browse/FELIX-5389?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15630209#comment-15630209
] 

Thomas Watson edited comment on FELIX-5389 at 11/2/16 7:51 PM:
---------------------------------------------------------------

I have found another issue which is causing the two NPEs reported here:

java.lang.NullPointerException
	at org.apache.felix.resolver.util.CandidateSelector.<init>(CandidateSelector.java:39)

java.lang.NullPointerException
        at org.apache.felix.resolver.Candidates.prepare(Candidates.java:946)

Both these errors are occurring because the capability, requirement, resource equals methods
are NOT symmetrical (a.equals(b) == b.equals(a)) when dealing with WrappedResource, WrappedCapability
and WrappedRequirement.  This causes major issues for our implementations of Map and Set in
the resolver.

For framework implementations that use the resolver this is not an issue because their implementations
of capability, requirement, and resource effectively use identity equality (default Object.equals()
behavior).  This is because even when the same bundle is installed multiple times in the framework
we must treat the two copies of the bundle Resource as unique.

BND does not use identity equality for its capability, requirement, resource implementations.
 Instead it tries to do equality check on the attributes/directives of the requirement or
capability and then does an equality check on the resource.  It does an equality check on
the resource by checking the osgi.content capability of the resource.  With this bit of implementation
knowledge of BND I decided to work around this by augmenting the osgi.content capability when
it is wrapped such that its 'url' key is different.  This causes bnd to do the 'right thing'
WRT to symmetric equality with the resolver's wrapped objects.

I released this fix along with the other issues I found with out of bounds errors.


was (Author: tjwatson):
I have found another issue which is causing the two NPEs reported here:

java.lang.NullPointerException
	at org.apache.felix.resolver.util.CandidateSelector.<init>(CandidateSelector.java:39)

java.lang.NullPointerException
        at org.apache.felix.resolver.Candidates.prepare(Candidates.java:946)

Both these errors are occurring because the capability, requirement, resource equals methods
is symmetrical (a.equals(b) == b.equals(a)) when dealing with WrappedResource, WrappedCapability
and WrappedRequirement.  This causes major issues for our implementations of Map and Set in
the resolver.

For framework implementations that use the resolver this is not an issue because their implementations
of capability, requirement, and resource effectively use identity equality (default Object.equals()
behavior).  This is because even when the same bundle is installed multiple times in the framework
we must treat the two copies of the bundle Resource as unique.

BND does not use identity equality for its capability, requirement, resource implementations.
 Instead it tries to do equality check on the attributes/directives of the requirement or
capability and then does an equality check on the resource.  It does an equality check on
the resource by checking the osgi.content capability of the resource.  With this bit of implementation
knowledge of BND I decided to work around this by augmenting the osgi.content capability when
it is wrapped such that its 'url' key is different.  This causes bnd to do the 'right thing'
WRT to symmetric equality with the resolver's wrapped objects.

I released this fix along with the other issues I found with out of bounds errors.

> NullPointerException in Candidates#prepare() method
> ---------------------------------------------------
>
>                 Key: FELIX-5389
>                 URL: https://issues.apache.org/jira/browse/FELIX-5389
>             Project: Felix
>          Issue Type: Bug
>          Components: Resolver
>    Affects Versions: resolver-1.10.0
>            Reporter: matteo rulli
>            Assignee: Thomas Watson
>
> Project where the errors appear: https://github.com/mrulli/com.flairbit.eclipsecon.onesix
> ----
> During the resolution of my bundles I get the following stacktrace (to trigger the resolution,
just do {{mvn install}} from the {{example.cassandra.itest.bndrun}} folder in the project
above):
> {code}
> [ERROR] Failed to execute goal biz.aQute.bnd:bnd-export-maven-plugin:3.4.0-SNAPSHOT:export
(default) on project example.cassandra.bndrun: null: MojoExecutionException: NullPointerException
-> [Help 1]
> org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal biz.aQute.bnd:bnd-export-maven-plugin:3.4.0-SNAPSHOT:export
(default) on project example.cassandra.bndrun: null
>  at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:216)
>  at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
>  at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
>  at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
>  at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)
>  at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
>  at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:120)
>  at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:347)
>  at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:154)
>  at org.apache.maven.cli.MavenCli.execute(MavenCli.java:582)
>  at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:214)
>  at org.apache.maven.cli.MavenCli.main(MavenCli.java:158)
>  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.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
>  at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
>  at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
>  at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
> Caused by: org.apache.maven.plugin.MojoExecutionException
>  at aQute.bnd.maven.export.plugin.ExportMojo.execute(ExportMojo.java:52)
>  at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:132)
>  at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
>  ... 19 more
> Caused by: java.lang.NullPointerException
>  at org.apache.felix.resolver.Candidates.prepare(Candidates.java:946)
>  at org.apache.felix.resolver.ResolverImpl.getInitialCandidates(ResolverImpl.java:502)
>  at org.apache.felix.resolver.ResolverImpl.doResolve(ResolverImpl.java:387)
>  at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:375)
>  at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:329)
>  at biz.aQute.resolve.BndResolver.resolve(BndResolver.java:29)
>  at biz.aQute.resolve.ResolveProcess.resolveRequired(ResolveProcess.java:75)
>  at biz.aQute.resolve.ProjectResolver.resolve(ProjectResolver.java:109)
>  at biz.aQute.resolve.ProjectResolver.getRunBundles(ProjectResolver.java:126)
>  at aQute.bnd.maven.export.plugin.ExportMojo.resolve(ExportMojo.java:86)
>  at aQute.bnd.maven.export.plugin.ExportMojo.export(ExportMojo.java:70)
>  at aQute.bnd.maven.export.plugin.ExportMojo.execute(ExportMojo.java:49)
>  ... 21 more
> {code}
> I tried to investigate a little bit this and I found that the NPE is generated in the
{{prepare()}} method - {{org.apache.felix.resolver.Candidates}} class, within the following
snippet:
> {code}
> m_candidateMap.put(r, cands.copy());
> for (Capability cand : cands.getRemainingCandidates())
> {
>     Set<Requirement> dependents = m_dependentMap.get(cand);
>     dependents.remove(origReq);
>     dependents.add(r);
> }
> {code}
> {{org.apache.felix.resolver.Candidates.m_dependentMap.get}} is invoked with key
> {code}
>     WrappedCapability: '[slf4j.api version=1.6.1] osgi.wiring.package; org.slf4j.impl'

>         m_cap: Provide[osgi.wiring.package]{version=1.6.1, osgi.wiring.package=org.slf4j.impl}{}
>         m_host: slf4j.api version=1.6.1
> {code}
> and this nullifies {{dependents}} var. The only WrappedCapabilities within the m_dependentMap
key set are the followings:
> {code}
>  [slf4j.api version=1.7.7] osgi.wiring.package; (&(osgi.wiring.package=org.slf4j)(version>=1.6.1))
>  [slf4j.api version=1.7.5] osgi.wiring.package; (&(osgi.wiring.package=org.slf4j.spi)(version>=1.6.1))
>  [slf4j.api version=1.7.5] osgi.wiring.package; (&(osgi.wiring.package=org.apache.log4j))
>  [slf4j.api version=1.6.1] osgi.wiring.package; (&(osgi.wiring.package=org.slf4j.impl)(version>=1.6.0))
>  [slf4j.api version=1.7.5] osgi.wiring.package; (&(osgi.wiring.package=org.slf4j.helpers)(version>=1.6.1))
>  [slf4j.api version=1.7.7] osgi.wiring.package; (&(osgi.wiring.package=org.apache.log4j))
>  [slf4j.api version=1.7.7] osgi.wiring.package; (&(osgi.wiring.package=org.slf4j.helpers)(version>=1.6.1))
>  [slf4j.api version=1.7.5] osgi.wiring.package; (&(osgi.wiring.package=org.slf4j.impl)(version>=1.6.0))
>  [slf4j.api version=1.7.7] osgi.wiring.package; (&(osgi.wiring.package=org.slf4j.spi)(version>=1.6.1))
>  [slf4j.api version=1.7.7] osgi.wiring.package; (&(osgi.wiring.package=org.slf4j.impl)(version>=1.6.0))
>  [slf4j.api version=1.7.5] osgi.wiring.package; (&(osgi.wiring.package=org.slf4j)(version>=1.6.1))
> {code}
> and none of them match the specified key above, at least as long as the WrappedCapability
equals method is concerned.
> In my opinion a meaningful error should be thrown by the resolver instead of throwing
NullPointerException. Or maybe it is just enough to skip actions on dependents in case null
value is returned?



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Mime
View raw message