[ https://issues.apache.org/jira/browse/FELIX-5285?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Clement Escoffier reassigned FELIX-5285: ---------------------------------------- Assignee: Clement Escoffier > iPojo does not delegate to the right classloader for Nullable Proxy > instantiation > --------------------------------------------------------------------------------- > > Key: FELIX-5285 > URL: https://issues.apache.org/jira/browse/FELIX-5285 > Project: Felix > Issue Type: Bug > Components: iPOJO > Reporter: Emmanuel Juste > Assignee: Clement Escoffier > Attachments: FELIX-5285.patch > > > iPojo runtime & api: 1.12.1 > Felix framework: 4.2.1 > This issue is similar to https://issues.apache.org/jira/browse/FELIX-2093 > This interface exist in v1.0 of an api and is exported by the system bundle > (felix) A > {code}package com.data.service > public interface DataService > { > public void search(String condition); > }{code} > A bundle, B, imports com.data.service;version=1.0: > {code}@Requires(optional = true) > private DataServiceImpl dataServiceImpl;{code} > where DataServiceImpl only implements the interface > All is working well at this point. > Then, the api evolves with a new method: > {code}package com.data.service > import com.data.service.conditions.Condition; > public interface DataService > { > public void search(String condition); > public void search(Condition condition); > }{code} > still exported by system bundle A but now as version 1.1 > The bundle B is not recompiled against this new version and does not import > the new package com.data.service.conditions > Now, when bundle B runs with v1.1 of the api, the requires of DataServiceImpl > is failing in Dependency.createNullableObject() > (http://felix.apache.org/ipojo/api/1.12.1/src-html/org/apache/felix/ipojo/handlers/dependency/Dependency.html > line 433) when creating the proxy: the proxy class is created w/o issue but > when an instance of this proxy class is done, there is a Class.forName() done > that fails to load the class Condition because it is not imported > Since the class Condition is already available and allows to create the proxy > class, it would make sense to use it instead of trying to load it thru the > bundle classloader > To achieve this, the methods of the specification could be browsed, for each > parameters and return types the classloader could be collected and given to > the NullableClassLoader. All classloaders could be asked to load the class. > At some point, the classloader of Condition would be queried and would return > the class > I don't know if this is breaking OSGi principles but I think it can fix this > issue > NB: I also tried to export the new api with uses directive: > com.data.service;version=1.1;uses:="com.data.service.conditions" > with no result. If I understand correctly uses directive is not supposed to > add implicit package import to bundle B, but are only used by the OSGi > framework to help it on the wiring process > Here's the cause exception thrown in java.lang.IllegalStateException: Cannot > create the Nullable object, a referenced class cannot be loaded: > {code}java.lang.NoClassDefFoundError: *** Class > 'com.data.service.conditions.Condition' was not found because bundle B [5] > does not import 'com.data.service.conditions' even though bundle > org.apache.felix.framework [0] does export it. Additionally, the class is > also available from the system class loader. There are two fixes: 1) Add an > import for 'com.data.service.conditions' to bundle B [5]; imports are > necessary for each class directly touched by bundle code or indirectly > touched, such as super classes if their methods are used. 2) Add package > 'com.data.service.conditions' to the 'org.osgi.framework.bootdelegation' > property; a library or VM bug can cause classes to be loaded by the wrong > class loader. The first approach is preferable for preserving modularity. > ***{code} > And the stack trace of the loadClass that fails: > {code}"[iPOJO] pool-1-thread-1@4605" daemon prio=5 tid=0x21 nid=NA runnable > java.lang.Thread.State: RUNNABLE > at > org.apache.felix.ipojo.handlers.dependency.Dependency$NullableClassLoader.loadClass(Dependency.java:1072) > at java.lang.Class.forName0(Class.java:-1) > at java.lang.Class.forName(Class.java:264) > at com.sun.proxy.$Proxy154.<clinit>(Unknown Source:-1) > at > sun.reflect.NativeConstructorAccessorImpl.newInstance0(NativeConstructorAccessorImpl.java:-1) > at > sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) > at > sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) > at java.lang.reflect.Constructor.newInstance(Constructor.java:422) > at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:739) > at > org.apache.felix.ipojo.handlers.dependency.Dependency.createNullableObject(Dependency.java:434) > at > org.apache.felix.ipojo.handlers.dependency.Dependency.start(Dependency.java:457) > at > org.apache.felix.ipojo.handlers.dependency.DependencyHandler.__M_start(DependencyHandler.java:496) > at > org.apache.felix.ipojo.handlers.dependency.DependencyHandler.start(DependencyHandler.java:-1) > at > org.apache.felix.ipojo.HandlerManager.start(HandlerManager.java:136) > at > org.apache.felix.ipojo.InstanceManager.start(InstanceManager.java:421) > at > org.apache.felix.ipojo.ComponentFactory.createInstance(ComponentFactory.java:179) > at > org.apache.felix.ipojo.IPojoFactory.createComponentInstance(IPojoFactory.java:319) > - locked <0x2a3b> (a org.apache.felix.ipojo.ComponentFactory) > at > org.apache.felix.ipojo.IPojoFactory.createComponentInstance(IPojoFactory.java:240) > at > org.apache.felix.ipojo.extender.internal.linker.ManagedType$InstanceSupport$1.call(ManagedType.java:312) > at > org.apache.felix.ipojo.extender.internal.linker.ManagedType$InstanceSupport$1.call(ManagedType.java:306) > at > org.apache.felix.ipojo.extender.internal.queue.JobInfoCallable.call(JobInfoCallable.java:114) > at java.util.concurrent.FutureTask.run(FutureTask.java:266) > at > java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) > at > java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) > at java.lang.Thread.run(Thread.java:745){code} -- This message was sent by Atlassian JIRA (v6.3.4#6332)