| Summary: | [DI] CNFE when OSGi service is injected | ||
|---|---|---|---|
| Product: | [Eclipse Project] Platform | Reporter: | Wim Jongman <wim.jongman> |
| Component: | Runtime | Assignee: | platform-runtime-inbox <platform-runtime-inbox> |
| Status: | CLOSED WORKSFORME | QA Contact: | |
| Severity: | normal | ||
| Priority: | P3 | CC: | dirk.fauth, mario.curcija, patrick, psuzzi, slewis |
| Version: | 4.5 | Keywords: | helpwanted |
| Target Milestone: | --- | ||
| Hardware: | PC | ||
| OS: | Windows 7 | ||
| Whiteboard: | |||
*** Bug 442764 has been marked as a duplicate of this bug. *** !ENTRY org.eclipse.e4.ui.workbench 1 0 2014-08-27 14:38:17.122 !MESSAGE LifeCycleManager - Eclipse context registered @lifecyclemanager INFO - RemoteBroker - Remote Broker constructed INFO - RemoteBroker - Remote broker: service trackers active INFO - HostConfigurationManager - Creating host configuration manager INFO - Class - Service ln.ont.sdaorj.services.IHostConnectionService.proxy@org.eclipse.ecf.remoteservice.RemoteServiceID[containerID=StringID[ecftcp://192.168.192.85:3787/server];containerRelativeID=1] from Name arrived at remote broker !ENTRY org.eclipse.ecf.osgi.services.remoteserviceadmin 4 0 2014-08-27 14:38:39.746 !MESSAGE org.eclipse.core.runtime.Status[plugin=org.eclipse.ecf.osgi.services.remoteserviceadmin;code=4;message=org.eclipse.ecf.osgi.services.remoteserviceadmin.RemoteServiceAdmin:loadInterfacesViaBundle:interface=ln.ont.sdaorj.services.simulation.IRunControllerService cannot be loaded by clientBundle=org.eclipse.e4.ui.workbench;severity4;exception=java.lang.ClassNotFoundException: ln.ont.sdaorj.services.simulation.IRunControllerService cannot be found by osgi.identity; osgi.identity="org.eclipse.e4.ui.workbench"; type="osgi.bundle"; version:Version="1.1.0.v20140228-1539"; singleton:="true";children=[]] !STACK 0 java.lang.ClassNotFoundException: ln.ont.sdaorj.services.simulation.IRunControllerService cannot be found by osgi.identity; osgi.identity="org.eclipse.e4.ui.workbench"; type="osgi.bundle"; version:Version="1.1.0.v20140228-1539"; singleton:="true" at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:416) at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:336) at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:328) at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:160) at java.lang.ClassLoader.loadClass(Unknown Source) at org.eclipse.osgi.internal.framework.EquinoxBundle.loadClass(EquinoxBundle.java:568) at org.eclipse.ecf.osgi.services.remoteserviceadmin.RemoteServiceAdmin.loadServiceInterfacesViaBundle(RemoteServiceAdmin.java:1635) at org.eclipse.ecf.osgi.services.remoteserviceadmin.RemoteServiceAdmin.createProxy(RemoteServiceAdmin.java:1694) at org.eclipse.ecf.osgi.services.remoteserviceadmin.RemoteServiceAdmin.access$5(RemoteServiceAdmin.java:1685) I've been struggling with this lately, and I'd really like to be able to use e4 DI with JAX-RS remote services. I've looked into the suggested solution on the duplicate bug entry, which is for the e4 OSGi context manager (EclipseContextOSGi) to use the originating bundle context to create the requested service. But it seems this would require significant changes to the EclipseContext API. I'm wondering if anyone has got this working in other ways (an e4 AddOn, etc.). One solution I've found is to add "DynamicImport-Package: *" to the manifest for the org.eclipse.e4.ui.workbench bundle. I'm not sure if this would be an option, I know it's considered something of a hack. But other framework bundles include this header to make class-loading more flexible, including Remote Services Admin. IIRC you want to use e4 injection to get an OSGi service, correct? Then you should use the @Service annotation with @Inject. Maybe there the classloading is done correctly. (In reply to Dirk Fauth from comment #4) > IIRC you want to use e4 injection to get an OSGi service, correct? Then you > should use the @Service annotation with @Inject. Maybe there the > classloading is done correctly. Yes, that does fix the class loading! The annotation bypasses the EclipseContextOSGi logic and loads the service using the consuming bundle's context. I would say this bug can be closed. The injection works when: 1. @Service annotation is used in addition to @Inject 2. Bundle-ActivationPolicy: lazy is set on the bundle using the injected service (In reply to Patrick Paulin from comment #5) > (In reply to Dirk Fauth from comment #4) > > IIRC you want to use e4 injection to get an OSGi service, correct? Then you > > should use the @Service annotation with @Inject. Maybe there the > > classloading is done correctly. > > Yes, that does fix the class loading! The annotation bypasses the > EclipseContextOSGi logic and loads the service using the consuming bundle's > context. FWIW: RSA does the same thing...i.e. loads the service class + all referenced classes via the consuming bundle's context. The distribution provider uses the OSGi wiring API to do so in a version-correct way. Then RSA + distribution provider creates the instance and dynamically puts in the OSGi service registry...as RSA spec defines. I don't happen to know how the @Inject + @Service handle dynamics (e.g. remote service proxy going away...or not being available at startup, etc). (In reply to Scott Lewis from comment #6) > (In reply to Patrick Paulin from comment #5) > > (In reply to Dirk Fauth from comment #4) > > > IIRC you want to use e4 injection to get an OSGi service, correct? Then you > > > should use the @Service annotation with @Inject. Maybe there the > > > classloading is done correctly. > > > > Yes, that does fix the class loading! The annotation bypasses the > > EclipseContextOSGi logic and loads the service using the consuming bundle's > > context. > > FWIW: RSA does the same thing...i.e. loads the service class + all > referenced classes via the consuming bundle's context. The distribution > provider uses the OSGi wiring API to do so in a version-correct way. Then > RSA + distribution provider creates the instance and dynamically puts in the > OSGi service registry...as RSA spec defines. > > I don't happen to know how the @Inject + @Service handle dynamics (e.g. > remote service proxy going away...or not being available at startup, etc). IIRC it supports the same mechanics like DS. But you need to use @Optional additionally so the reinjection works if a service goes away. As an alternative I often use some wrapper service that is always available for injection in E4. And that service uses @Reference for consuming the remote service. This way the OSGi dynamics are fully supported while the E4 injection works with an always available service. Thanks! |
Hi, I have a DI use case that affects the proper working of the OSGi RSA (Remote Service Admin) specification inside Eclipse E4 [1]. A service implementing interface XYZ is consumed by an E4 application through DI like this: class foo{ @inject @optional XYZ service; } A remote service is received in the E4 application and the RSE spec implementer (ECF) must load this class. This is done through the bundle that tracks this service because this bundle knows about this class. This is discussed in chapter 122.5.6 in [1] In the case of DI, it is tracking OSGi services with the org.eclipse.e4.ui.workbench bundle. ECF sees this and tries to load the XYZ class through this bundle. This fails with a CNFE. Instead, DI should track the service with the bundle of the requesting object. This ensures proxies of any kind to properly load a class. [1] http://www.osgi.org/download/r4v42/r4.enterprise.pdf