eclipse-m2e / m2e-core

Eclipse Public License 2.0
113 stars 115 forks source link

Updating 2022-12 to 2023-03 results in 'Circular reference detected trying to get service {org.eclipse.m2e.core.project.IMavenProjectChangedListener}' #1210

Open merks opened 1 year ago

merks commented 1 year ago

Download this package:

https://www.eclipse.org/downloads/packages/release/2022-12/r/eclipse-ide-eclipse-committers

Start the IDE. Disable all update sites in Window -> Preferences -> Install/Update -> Available Software Sites and add this site:

https://download.eclipse.org/releases/2023-03/

Run Help -> Check for Updates and install all the available updates. Restart. Open the Error Log view and notice that it contains this error:

eclipse.buildId=4.27.0.20230112-0751
java.version=17.0.5
java.vendor=Eclipse Adoptium
BootLoader constants: OS=win32, ARCH=x86_64, WS=win32, NL=en_US
Framework arguments:  -product org.eclipse.epp.package.committers.product -product org.eclipse.epp.package.committers.product
Command-line arguments:  -os win32 -ws win32 -arch x86_64 -product org.eclipse.epp.package.committers.product -product org.eclipse.epp.package.committers.product -data file:/D:/Users/test17/epp/ws/

org.apache.felix.scr
Error
Tue Jan 17 09:23:53 CET 2023
bundle org.apache.felix.scr:2.2.4 (46) Circular reference detected trying to get service {org.eclipse.m2e.core.project.IMavenProjectChangedListener}={service.id=237, service.bundleid=275, service.scope=bundle, osgi.ds.satisfying.condition.target=(osgi.condition.id=true), component.name=org.eclipse.m2e.core.internal.project.WorkspaceStateWriter, component.id=78}
 stack of references: ServiceReference: {org.eclipse.m2e.core.project.IMavenProjectChangedListener}={service.id=237, service.bundleid=275, service.scope=bundle, osgi.ds.satisfying.condition.target=(osgi.condition.id=true), component.name=org.eclipse.m2e.core.internal.project.WorkspaceStateWriter, component.id=78}
ServiceReference: {org.eclipse.m2e.core.project.IMavenProjectRegistry}={service.id=230, service.bundleid=275, service.scope=bundle, osgi.ds.satisfying.condition.target=(osgi.condition.id=true), component.name=org.eclipse.m2e.core.internal.project.registry.MavenProjectManager, component.id=81}
    Dependency: DependencyManager: Component [Component: org.eclipse.m2e.core.embedder.MavenModelManager (67)] reference [projectManager]

java.lang.Exception: stack trace
    at org.apache.felix.scr.impl.ComponentRegistry.enterCreate(ComponentRegistry.java:493)
    at org.apache.felix.scr.impl.BundleComponentActivator.enterCreate(BundleComponentActivator.java:722)
    at org.apache.felix.scr.impl.manager.SingleComponentManager.getService(SingleComponentManager.java:901)
    at org.eclipse.osgi.internal.serviceregistry.ServiceFactoryUse$1.run(ServiceFactoryUse.java:218)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:318)
    at org.eclipse.osgi.internal.serviceregistry.ServiceFactoryUse.factoryGetService(ServiceFactoryUse.java:215)
    at org.eclipse.osgi.internal.serviceregistry.ServiceFactoryUse.getService(ServiceFactoryUse.java:114)
    at org.eclipse.osgi.internal.serviceregistry.ServiceConsumer$2.getService(ServiceConsumer.java:48)
    at org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl.getService(ServiceRegistrationImpl.java:568)
    at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.getService(ServiceRegistry.java:542)
    at org.eclipse.osgi.internal.framework.BundleContextImpl.getService(BundleContextImpl.java:660)
    at org.apache.felix.scr.impl.manager.SingleRefPair.getServiceObject(SingleRefPair.java:88)
    at org.apache.felix.scr.impl.inject.methods.BindMethod.getServiceObject(BindMethod.java:675)
    at org.apache.felix.scr.impl.manager.DependencyManager.getServiceObject(DependencyManager.java:2612)
    at org.apache.felix.scr.impl.manager.DependencyManager$MultipleDynamicCustomizer.prebind(DependencyManager.java:434)
    at org.apache.felix.scr.impl.manager.DependencyManager.prebind(DependencyManager.java:1830)
    at org.apache.felix.scr.impl.manager.AbstractComponentManager.collectDependencies(AbstractComponentManager.java:1060)
    at org.apache.felix.scr.impl.manager.SingleComponentManager.getServiceInternal(SingleComponentManager.java:955)
    at org.apache.felix.scr.impl.manager.SingleComponentManager.getService(SingleComponentManager.java:920)
    at org.eclipse.osgi.internal.serviceregistry.ServiceFactoryUse$1.run(ServiceFactoryUse.java:218)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:318)
    at org.eclipse.osgi.internal.serviceregistry.ServiceFactoryUse.factoryGetService(ServiceFactoryUse.java:215)
    at org.eclipse.osgi.internal.serviceregistry.ServiceFactoryUse.getService(ServiceFactoryUse.java:114)
    at org.eclipse.osgi.internal.serviceregistry.ServiceConsumer$2.getService(ServiceConsumer.java:48)
    at org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl.getService(ServiceRegistrationImpl.java:568)
    at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.getService(ServiceRegistry.java:542)
    at org.eclipse.osgi.internal.framework.BundleContextImpl.getService(BundleContextImpl.java:660)
    at org.apache.felix.scr.impl.manager.SingleRefPair.getServiceObject(SingleRefPair.java:88)
    at org.apache.felix.scr.impl.inject.field.FieldHandler$ReferenceMethodImpl.getServiceObject(FieldHandler.java:550)
    at org.apache.felix.scr.impl.manager.DependencyManager.getServiceObject(DependencyManager.java:2612)
    at org.apache.felix.scr.impl.manager.DependencyManager$SingleStaticCustomizer.prebind(DependencyManager.java:1401)
    at org.apache.felix.scr.impl.manager.DependencyManager.prebind(DependencyManager.java:1830)
    at org.apache.felix.scr.impl.manager.AbstractComponentManager.collectDependencies(AbstractComponentManager.java:1060)
    at org.apache.felix.scr.impl.manager.SingleComponentManager.getServiceInternal(SingleComponentManager.java:955)
    at org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:776)
    at org.apache.felix.scr.impl.manager.DependencyManager$SingleStaticCustomizer.addedService(DependencyManager.java:1274)
    at org.apache.felix.scr.impl.manager.DependencyManager$SingleStaticCustomizer.addedService(DependencyManager.java:1225)
    at org.apache.felix.scr.impl.manager.ServiceTracker$Tracked.customizerAdded(ServiceTracker.java:1232)
    at org.apache.felix.scr.impl.manager.ServiceTracker$Tracked.customizerAdded(ServiceTracker.java:1152)
    at org.apache.felix.scr.impl.manager.ServiceTracker$AbstractTracked.trackAdding(ServiceTracker.java:959)
    at org.apache.felix.scr.impl.manager.ServiceTracker$AbstractTracked.track(ServiceTracker.java:895)
    at org.apache.felix.scr.impl.manager.ServiceTracker$Tracked.serviceChanged(ServiceTracker.java:1184)
    at org.apache.felix.scr.impl.BundleComponentActivator$ListenerInfo.serviceChanged(BundleComponentActivator.java:116)
    at org.eclipse.osgi.internal.serviceregistry.FilteredServiceListener.serviceChanged(FilteredServiceListener.java:123)
    at org.eclipse.osgi.internal.framework.BundleContextImpl.dispatchEvent(BundleContextImpl.java:961)
    at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234)
    at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:151)
    at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.publishServiceEventPrivileged(ServiceRegistry.java:945)
    at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.publishServiceEvent(ServiceRegistry.java:882)
    at org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl.register(ServiceRegistrationImpl.java:144)
    at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.registerService(ServiceRegistry.java:270)
    at org.eclipse.osgi.internal.framework.BundleContextImpl.registerService(BundleContextImpl.java:500)
    at org.apache.felix.scr.impl.manager.AbstractComponentManager$3.register(AbstractComponentManager.java:929)
    at org.apache.felix.scr.impl.manager.AbstractComponentManager$3.register(AbstractComponentManager.java:915)
    at org.apache.felix.scr.impl.manager.RegistrationManager.changeRegistration(RegistrationManager.java:133)
    at org.apache.felix.scr.impl.manager.AbstractComponentManager.registerService(AbstractComponentManager.java:984)
    at org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:752)
    at org.apache.felix.scr.impl.manager.DependencyManager$SingleStaticCustomizer.addedService(DependencyManager.java:1274)
    at org.apache.felix.scr.impl.manager.DependencyManager$SingleStaticCustomizer.addedService(DependencyManager.java:1225)
    at org.apache.felix.scr.impl.manager.ServiceTracker$Tracked.customizerAdded(ServiceTracker.java:1232)
    at org.apache.felix.scr.impl.manager.ServiceTracker$Tracked.customizerAdded(ServiceTracker.java:1152)
    at org.apache.felix.scr.impl.manager.ServiceTracker$AbstractTracked.trackAdding(ServiceTracker.java:959)
    at org.apache.felix.scr.impl.manager.ServiceTracker$AbstractTracked.track(ServiceTracker.java:895)
    at org.apache.felix.scr.impl.manager.ServiceTracker$Tracked.serviceChanged(ServiceTracker.java:1184)
    at org.apache.felix.scr.impl.BundleComponentActivator$ListenerInfo.serviceChanged(BundleComponentActivator.java:116)
    at org.eclipse.osgi.internal.serviceregistry.FilteredServiceListener.serviceChanged(FilteredServiceListener.java:123)
    at org.eclipse.osgi.internal.framework.BundleContextImpl.dispatchEvent(BundleContextImpl.java:961)
    at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234)
    at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:151)
    at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.publishServiceEventPrivileged(ServiceRegistry.java:945)
    at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.publishServiceEvent(ServiceRegistry.java:882)
    at org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl.register(ServiceRegistrationImpl.java:144)
    at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.registerService(ServiceRegistry.java:270)
    at org.eclipse.osgi.internal.framework.BundleContextImpl.registerService(BundleContextImpl.java:500)
    at org.eclipse.osgi.internal.framework.BundleContextImpl.registerService(BundleContextImpl.java:519)
    at org.eclipse.osgi.internal.framework.BundleContextImpl.registerService(BundleContextImpl.java:1047)
    at org.eclipse.core.resources.ResourcesPlugin$WorkspaceInitCustomizer.addingService(ResourcesPlugin.java:574)
    at org.eclipse.core.resources.ResourcesPlugin$WorkspaceInitCustomizer.addingService(ResourcesPlugin.java:1)
    at org.osgi.util.tracker.ServiceTracker$Tracked.customizerAdding(ServiceTracker.java:943)
    at org.osgi.util.tracker.ServiceTracker$Tracked.customizerAdding(ServiceTracker.java:1)
    at org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:256)
    at org.osgi.util.tracker.AbstractTracked.trackInitial(AbstractTracked.java:183)
    at org.osgi.util.tracker.ServiceTracker.open(ServiceTracker.java:321)
    at org.osgi.util.tracker.ServiceTracker.open(ServiceTracker.java:264)
    at org.eclipse.core.resources.ResourcesPlugin.start(ResourcesPlugin.java:545)
    at org.eclipse.osgi.internal.framework.BundleContextImpl$2.run(BundleContextImpl.java:818)
    at org.eclipse.osgi.internal.framework.BundleContextImpl$2.run(BundleContextImpl.java:1)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:569)
    at org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:810)
    at org.eclipse.osgi.internal.framework.BundleContextImpl.start(BundleContextImpl.java:767)
    at org.eclipse.osgi.internal.framework.EquinoxBundle.startWorker0(EquinoxBundle.java:1032)
    at org.eclipse.osgi.internal.framework.EquinoxBundle$EquinoxModule.startWorker(EquinoxBundle.java:371)
    at org.eclipse.osgi.container.Module.doStart(Module.java:605)
    at org.eclipse.osgi.container.Module.start(Module.java:468)
    at org.eclipse.osgi.framework.util.SecureAction.start(SecureAction.java:513)
    at org.eclipse.osgi.internal.hooks.EclipseLazyStarter.postFindLocalClass(EclipseLazyStarter.java:117)
    at org.eclipse.osgi.internal.loader.classpath.ClasspathManager.findLocalClass(ClasspathManager.java:570)
    at org.eclipse.osgi.internal.loader.ModuleClassLoader.findLocalClass(ModuleClassLoader.java:335)
    at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:397)
    at org.eclipse.osgi.internal.loader.sources.SingleSourcePackage.loadClass(SingleSourcePackage.java:41)
    at org.eclipse.osgi.internal.loader.BundleLoader.findClass0(BundleLoader.java:496)
    at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:416)
    at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:168)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
    at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:153)
    at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:136)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:402)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:659)
    at org.eclipse.equinox.launcher.Main.basicRun(Main.java:596)
    at org.eclipse.equinox.launcher.Main.run(Main.java:1467)
laeubi commented 1 year ago

IMavenProjectChangedListener are dynamic services and thus this is usually not a error (even though eclipse handles it as such).

merks commented 1 year ago

@jonahgraham

FYI, I opened this for the issue I mentioned in epp-dev.

laeubi commented 1 year ago

FYI, I opened this for the issue I mentioned in epp-dev.

So what issue are you seeing as a result of this? If everything is working, m2e can hardly do anything...

merks commented 1 year ago

I don't know what these services do nor what this failure means. I'm not an expert. I get the impression that it means that some component will not be properly initialized as a result. Perhaps as an expert you are able to determine if this is a bogus diagnosis by the platform or if something really doesn't work. You mention that this is "usually" not an error which seems to cast doubt on whether it is or isn't an error and whether eclipse is handling it poorly versus correctly. It's easy to reproduce the problem via the described steps...

laeubi commented 1 year ago

How to see if anything goes wrong

If everything works fine there is mostly no problem, but you can take a look at the OSGi console and type list that will show you all components, and if they are all satisfied it should be fine:

grafik

WARNING: This console is connected to the current running instance of Eclipse!
____________________________
Welcome to Apache Felix Gogo

g! list

... will list all components here...

Why it is usually not a problem

In DS you define references to services and you declare what services your component offers. These reference can be either static or dynamic.

What happen now is, that DS tries to satisfies as much as possible from C1 (and therefore tries to create C2) but detects that there is a circular dependency chain and print the warning/error/... as Service A is optional, now DS creates C1 without it (what works because Service A is optional), now C2 can be constructed and will be injected into C1 (because it is dynamic).

So in the end, we have everything setup (even the optional one), even though there is one configuration that has a cycle... you can compare this a bit with P2, that if it detects a conflict on install, tries to compute an alternative configuration that can be satisfied in the end (e.g. by leaving out an optional greedy requirement).

A usual example is a list of listeners: Your component can work without notify other components and they can come and go dynamically.

laeubi commented 1 year ago

@tjwatson as you are maintainer at Felix SCR: Can we do anything here?

tjwatson commented 1 year ago

Not sure what you have in mind. AFAICT Felix SCR is following the spec'ed behavior with respect to circular references:

https://docs.osgi.org/specification/osgi.cmpn/8.0.0/service.component.html#service.component-circular.references

perhaps a potential improvement is if the reference is optional it could log a warning instead. But that is not always going to be clear if the optional reference is a few levels up from the actual circular error detection.

laeubi commented 1 year ago

I'm not sure if

However, if one of the references in the cycle has optional cardinality SCR must break the cycle. The reference with the optional cardinality can be satisfied and bound to zero target services. Therefore the cycle is broken and the other references may be satisfied.

indicates that in such a case no error must be logged because actually the component can be activated?!?

tjwatson commented 1 year ago

indicates that in such a case no error must be logged because actually the component can be activated?!?

A-optional->B->C->D->A

Here we are creating B to satisfy optional reference from A. In doing so we try to activate B->C->D-> then detect the cycle. Here D cannot be activated and I believe an error should be logged. That bubbles up and A can still be satisfied because B is optional.

laeubi commented 1 year ago

Here D cannot be activated and I believe an error should be logged.

D cannot be activated right now, but as soon as A is active, B will become injected and everything works. So I think the condition to log an error should be that the chain is a strong cycle with no (intermediate) optional reference.

tjwatson commented 1 year ago

We probably could avoid logging an error in this case. I'm unsure how much that will complicate the implementation at this point. You are free to open an issue with Felix to discuss there. Contributions welcome.