Add support CDI in plain OSGi bundles (GLASSFISH-19215)

[GLASSFISH-19324] Instance.select(clazz).get() throw IllegalArgumentException: Created: 13/Nov/12  Updated: 13/Nov/12

Status: Open
Project: glassfish
Component/s: OSGi-JavaEE
Affects Version/s: future release
Fix Version/s: None

Type: Sub-task Priority: Major
Reporter: TangYong Assignee: Sanjeeb Sahoo
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Based current patch, while testing(firstly deploying , then stop-domain, again start-domain), IllegalArgumentException is thrown and happens on OSGiServicePublisher.RegisterOSGiService() method as following:

[#|2012-11-13T17:26:53.937+0900|SEVERE|44.0|javax.enterprise.logging.stderr|_ThreadID=12;_ThreadName=pool-8-thread-1;_TimeMillis=1352795213937;_LevelValue=1000;|java.lang.IllegalArgumentException: interface org.acme.myservice.MyServiceInf is not visible from class loader
at java.lang.reflect.Proxy.getProxyClass(Proxy.java:353)
at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:581)
at org.glassfish.osgicdi.impl.OSGiServiceFactory.createServiceProxy(OSGiServiceFactory.java:111)
at org.glassfish.osgicdi.impl.OSGiServiceFactory.getService(OSGiServiceFactory.java:86)
at org.glassfish.osgicdi.impl.OSGiServiceExtension$OSGiServiceBean.create(OSGiServiceExtension.java:295)
at org.jboss.weld.context.unbound.DependentContextImpl.get(DependentContextImpl.java:68)
at org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:608)
at org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:674)
at org.jboss.weld.injection.FieldInjectionPoint.inject(FieldInjectionPoint.java:136)
at org.jboss.weld.util.Beans.injectBoundFields(Beans.java:763)
at org.jboss.weld.util.Beans.injectFieldsAndInitializers(Beans.java:772)
at org.jboss.weld.bean.ManagedBean$ManagedBeanInjectionTarget$1$1.proceed(ManagedBean.java:161)
at org.jboss.weld.injection.InjectionContextImpl.run(InjectionContextImpl.java:48)
at org.jboss.weld.bean.ManagedBean$ManagedBeanInjectionTarget$1.work(ManagedBean.java:157)
at org.jboss.weld.bean.ManagedBean$FixInjectionPoint.run(ManagedBean.java:131)
at org.jboss.weld.bean.ManagedBean$ManagedBeanInjectionTarget.inject(ManagedBean.java:153)
at org.jboss.weld.bean.ManagedBean.create(ManagedBean.java:293)
at org.jboss.weld.context.unbound.DependentContextImpl.get(DependentContextImpl.java:68)
at org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:608)
at org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:635)
at org.jboss.weld.bean.builtin.InstanceImpl.get(InstanceImpl.java:108)
at org.glassfish.osgicdi.impl.OSGiServicePublisher.RegisterOSGiService(OSGiServicePublisher.java:89)
at org.glassfish.osgicdi.impl.OSGiServiceExtension.publishOSGiService(OSGiServiceExtension.java:272)
at org.glassfish.osgicdi.impl.OSGiCDIExtender$BeanBundleTrackerCustomizer.addingBundle(OSGiCDIExtender.java:151)
at org.osgi.util.tracker.BundleTracker$Tracked.customizerAdding(BundleTracker.java:482)
at org.osgi.util.tracker.BundleTracker$Tracked.customizerAdding(BundleTracker.java:424)
at org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:262)
at org.osgi.util.tracker.AbstractTracked.trackInitial(AbstractTracked.java:185)
at org.osgi.util.tracker.BundleTracker.open(BundleTracker.java:163)
at org.glassfish.osgicdi.impl.OSGiCDIExtender.start(OSGiCDIExtender.java:92)
at org.glassfish.osgijavaeebase.ExtenderManager$ExtenderTracker.addingService(ExtenderManager.java:144)
at org.osgi.util.tracker.ServiceTracker$Tracked.customizerAdding(ServiceTracker.java:980)
at org.osgi.util.tracker.ServiceTracker$Tracked.customizerAdding(ServiceTracker.java:906)
at org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:262)
at org.osgi.util.tracker.AbstractTracked.trackInitial(AbstractTracked.java:185)
at org.osgi.util.tracker.ServiceTracker.open(ServiceTracker.java:348)
at org.osgi.util.tracker.ServiceTracker.open(ServiceTracker.java:283)
at org.glassfish.osgijavaeebase.ExtenderManager.startExtenders(ExtenderManager.java:109)
at org.glassfish.osgijavaeebase.ExtenderManager.access$100(ExtenderManager.java:67)
at org.glassfish.osgijavaeebase.ExtenderManager$GlassFishServerTracker$1.run(ExtenderManager.java:192)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)

#]


 Comments   
Comment by TangYong [ 13/Nov/12 ]

A fixing way is that setting current thread's ContextClassLoader into Bundle's Classloader as following:

ClassLoader oldTCC = Thread.currentThread().getContextClassLoader();

try

{ ClassLoader newTCC = clazz.getClassLoader(); Thread.currentThread().setContextClassLoader(newTCC); service = instance.select(clazz).get(); }

finally

{ Thread.currentThread().setContextClassLoader(oldTCC); }

If having more time, I will investigate whether should fix the problem on earlier time or not.

Comment by TangYong [ 13/Nov/12 ]

The following fix way is not right while using ACLSingletonProvider, and right way is to set Thread current context classloader on earlier time and need to set scanned bundle's classloader. So, the following is the right fixing way:

1 define a new private TCCLClassLoader in OSGiCDIExtender

private static class TCCLClassLoader extends ClassLoader {
private final Bundle bundle;

private final ClassLoader infra;

public TCCLClassLoader(Bundle bundle, ClassLoader infraClassLoader)

{ this.bundle = bundle; this.infra = infraClassLoader; }

@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
Class<?> loadedClass = null;
try

{ loadedClass = bundle.loadClass(name); }

catch (ClassNotFoundException cnfe)

{ // todo : filter on utils class only loadedClass = infra.loadClass(name); }

return loadedClass;
}

@Override
public Enumeration<URL> getResources(String s) throws IOException {
Set<URL> urls = new HashSet<URL>();
Enumeration enumBundle = bundle.getResources(s);
Enumeration enumInfra = infra.getResources(s);
if (enumBundle != null)

{ urls.addAll(Collections.list(enumBundle)); }

if (enumInfra != null)

{ urls.addAll(Collections.list(enumInfra)); }

return Collections.enumeration(urls);
}
}

2 setting current thread's ContextClassLoader into the TCCLClassLoader before starting Weld Container

ClassLoader oldTCC = Thread.currentThread().getContextClassLoader();

try{
ClassLoader newTCC = new TCCLClassLoader(bundle, this.getClass().getClassLoader());
Thread.currentThread().setContextClassLoader(newTCC);
...

Generated at Tue Jul 26 18:23:14 UTC 2016 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.