[ https://issues.apache.org/jira/browse/FELIX-6353?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Carsten Ziegeler reassigned FELIX-6353: --------------------------------------- Assignee: Tom Watson > Constructor injection: activation with optional reference fails if service > not available > ---------------------------------------------------------------------------------------- > > Key: FELIX-6353 > URL: https://issues.apache.org/jira/browse/FELIX-6353 > Project: Felix > Issue Type: Bug > Components: Declarative Services (SCR) > Affects Versions: scr-2.1.24 > Reporter: Tobias Gunkel > Assignee: Tom Watson > Priority: Major > Fix For: scr-2.1.26 > > Attachments: constructorinjection.patch, > optionalreferenceconstructor-example.zip > > > A service that uses constructor injection for an optional service will crash > with an "activation failed" exception if the optional service is not > available. > According to the OSGi R7 specification a "null" value should be injected > instead. > > Example: > {code} > @Activate > public SomeService( > @Reference(cardinality = ReferenceCardinality.OPTIONAL) > OptionalService optionalService) > {} > {code} > The above code works if an OptionalService instance is present but it fails > and crashes if no OptionalService instance is present during activation time: > Error message in log: > {code} > ERROR : bundle optionalreferenceconstructor:0.1.0.. > (1)[optionalreferenceconstructor.SomeService(0)] : Error during instantiation > of the implementation object: Unable to get service for reference > optionalService > {code} > Stack trace shown with scr:info: > {code} > State: FAILED ACTIVATION > References: (total 1) > - optionalService: optionalreferenceconstructor.OptionalService SATISFIED > 0..1 static > target=(*) scope=bundle (no active bindings) > Failure: java.lang.InstantiationException: Unable to get service for > reference optionalService > java.lang.InstantiationException: Unable to get service for reference > additionalSettingsStorage at > org.apache.felix.scr.impl.inject.internal.ComponentConstructorImpl.newInstance(ComponentConstructorImpl.java:301) > at > org.apache.felix.scr.impl.manager.SingleComponentManager.createImplementationObject(SingleComponentManager.java:286) > at > org.apache.felix.scr.impl.manager.SingleComponentManager.createComponent(SingleComponentManager.java:115) > at > org.apache.felix.scr.impl.manager.SingleComponentManager.getService(SingleComponentManager.java:1000) > at > org.apache.felix.scr.impl.manager.SingleComponentManager.getServiceInternal(SingleComponentManager.java:973) > at > org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:785) > at > org.apache.felix.scr.impl.manager.DependencyManager$SingleStaticCustomizer.addedService(DependencyManager.java:1271) > at > org.apache.felix.scr.impl.manager.DependencyManager$SingleStaticCustomizer.addedService(DependencyManager.java:1222) > at > org.apache.felix.scr.impl.manager.ServiceTracker$Tracked.customizerAdded(ServiceTracker.java:1200) > at > org.apache.felix.scr.impl.manager.ServiceTracker$Tracked.customizerAdded(ServiceTracker.java:1121) > at > org.apache.felix.scr.impl.manager.ServiceTracker$AbstractTracked.trackAdding(ServiceTracker.java:928) > at > org.apache.felix.scr.impl.manager.ServiceTracker$AbstractTracked.track(ServiceTracker.java:864) > at > org.apache.felix.scr.impl.manager.ServiceTracker$Tracked.serviceChanged(ServiceTracker.java:1152) > at > org.apache.felix.scr.impl.BundleComponentActivator$ListenerInfo.serviceChanged(BundleComponentActivator.java:114) > at > org.apache.felix.framework.EventDispatcher.invokeServiceListenerCallback(EventDispatcher.java:990) > at > org.apache.felix.framework.EventDispatcher.fireEventImmediately(EventDispatcher.java:838) > at > org.apache.felix.framework.EventDispatcher.fireServiceEvent(EventDispatcher.java:545) > at org.apache.felix.framework.Felix.fireServiceEvent(Felix.java:4833) at > org.apache.felix.framework.Felix.registerService(Felix.java:3804) at > org.apache.felix.framework.BundleContextImpl.registerService(BundleContextImpl.java:328) > at > ... > {code} > It seems that the ComponentConstructorImpl (line 301) does only check for > multiple cardinality but not for optional cardinality. > Propably ComponentConstructorImpl.java (line 299) should be: > {code} > if ( !refMetadata.isMultiple()) > { > if ( !refMetadata.isOptional() && (ref == null) ) > { > throw new InstantiationException("Unable to get service for > reference " + refMetadata.getName()); > } > } > {code} > Instead of: > {code} > if ( !refMetadata.isMultiple()) > { > if ( ref == null ) > { > throw new InstantiationException("Unable to get service for > reference " + refMetadata.getName()); > } > } > {code} > The change is also attached a patch file. Please note that I did not have the > opportunity to test the change. It might not fix the problem or cause other > crashes. -- This message was sent by Atlassian Jira (v8.3.4#803005)