[ 
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)

Reply via email to