karaf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From b..@petinou.fr
Subject Re: How to manage several service instances with declarative services?
Date Thu, 14 Jan 2016 14:54:47 GMT
Hi everyone,

For those interested, I found the solution to my problem:

By looking in Felix SCR source code I found the lines causing the 
exception:

// field value type
if ( !m_isMultiple )
{
     // value type must not be specified for unary references
     if ( m_field_collection_type != null )
     {
         throw componentMetadata.validationFailure( "Field value type 
must not be set for unary field references." );
     }
}

It seems Felix SCR is not happy because the attribute 
m_field_collection_type is set to "service" in the component XML (i.e. 
not null), while no cardinality is specified...

I thus changed my annotation like this:

@Reference(cardinality = ReferenceCardinality.AT_LEAST_ONE)
private List<FileReaderService> availableServices;

I also added a factory service consumer in order to test the application 
and it works!

For those interested, the fixed source code is available here:
https://github.com/neopium/FileReader

Kind regards,
Ben

Le 12.01.2016 11:21, ben@petinou.fr a écrit :
> Hi David,
> 
> I just pushed my sample project on GitHub: 
> https://github.com/neopium/FileReader
> 
> You can get it from here and build it. I configured it so that it
> generates a Karaf assembly with the required feature. When you start
> karaf and type scr:list, you see the two readers with null status. The
> factory is not there.
> 
> Here is the generated component xml file:
> 
> <?xml version="1.0" encoding="UTF-8"?>
> <scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.3.0"
> name="org.test.reader.service.factory.FileReaderFactory">
>   <implementation 
> class="org.test.reader.service.factory.FileReaderFactory"/>
>   <service>
>     <provide interface="org.test.reader.service.ReaderFactoryService"/>
>   </service>
>   <reference name="availableServices"
> interface="org.test.reader.service.FileReaderService"
> field="availableServices" field-collection-type="service"/>
> </scr:component>
> 
> Here is the full stacktrace:
> 
> 2016-01-12 11:12:36,961 | ERROR | pool-8-thread-1  |
> file-reader-service-impl         | 9 - file-reader-service-impl -
> 1.0.0.SNAPSHOT | [org.test.reader.service.factory.FileReaderFactory]
> Cannot register Component
> org.osgi.service.component.ComponentException: Component
> org.test.reader.service.factory.FileReaderFactory validation failed:
> Field value type must not be set for unary field references.
>         at
> org.apache.felix.scr.impl.metadata.ComponentMetadata.validationFailure(ComponentMetadata.java:953)[24:org.apache.felix.scr:2.0.2]
>         at
> org.apache.felix.scr.impl.metadata.ReferenceMetadata.validate(ReferenceMetadata.java:710)[24:org.apache.felix.scr:2.0.2]
>         at
> org.apache.felix.scr.impl.metadata.ComponentMetadata.validate(ComponentMetadata.java:873)[24:org.apache.felix.scr:2.0.2]
>         at
> org.apache.felix.scr.impl.BundleComponentActivator.loadDescriptor(BundleComponentActivator.java:454)[24:org.apache.felix.scr:2.0.2]
>         at
> org.apache.felix.scr.impl.BundleComponentActivator.initialize(BundleComponentActivator.java:309)[24:org.apache.felix.scr:2.0.2]
>         at
> org.apache.felix.scr.impl.BundleComponentActivator.<init>(BundleComponentActivator.java:270)[24:org.apache.felix.scr:2.0.2]
>         at
> org.apache.felix.scr.impl.Activator.loadComponents(Activator.java:358)[24:org.apache.felix.scr:2.0.2]
>         at
> org.apache.felix.scr.impl.Activator.access$000(Activator.java:53)[24:org.apache.felix.scr:2.0.2]
>         at
> org.apache.felix.scr.impl.Activator$ScrExtension.start(Activator.java:260)[24:org.apache.felix.scr:2.0.2]
>         at
> org.apache.felix.utils.extender.AbstractExtender.createExtension(AbstractExtender.java:259)[24:org.apache.felix.scr:2.0.2]
>         at
> org.apache.felix.utils.extender.AbstractExtender.modifiedBundle(AbstractExtender.java:232)[24:org.apache.felix.scr:2.0.2]
>         at
> org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:482)[org.osgi.core-6.0.0.jar:]
>         at
> org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:415)[org.osgi.core-6.0.0.jar:]
>         at
> org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:232)[org.osgi.core-6.0.0.jar:]
>         at
> org.osgi.util.tracker.BundleTracker$Tracked.bundleChanged(BundleTracker.java:444)[org.osgi.core-6.0.0.jar:]
>         at
> org.apache.felix.framework.util.EventDispatcher.invokeBundleListenerCallback(EventDispatcher.java:916)[org.apache.felix.framework-5.4.0.jar:]
>         at
> org.apache.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:835)[org.apache.felix.framework-5.4.0.jar:]
>         at
> org.apache.felix.framework.util.EventDispatcher.fireBundleEvent(EventDispatcher.java:517)[org.apache.felix.framework-5.4.0.jar:]
>         at
> org.apache.felix.framework.Felix.fireBundleEvent(Felix.java:4541)[org.apache.felix.framework-5.4.0.jar:]
>         at
> org.apache.felix.framework.Felix.startBundle(Felix.java:2172)[org.apache.felix.framework-5.4.0.jar:]
>         at
> org.apache.felix.framework.BundleImpl.start(BundleImpl.java:998)[org.apache.felix.framework-5.4.0.jar:]
>         at
> org.apache.felix.framework.BundleImpl.start(BundleImpl.java:984)[org.apache.felix.framework-5.4.0.jar:]
>         at
> org.apache.karaf.features.internal.service.FeaturesServiceImpl.startBundle(FeaturesServiceImpl.java:1189)[7:org.apache.karaf.features.core:4.0.3]
>         at
> org.apache.karaf.features.internal.service.Deployer.deploy(Deployer.java:836)[7:org.apache.karaf.features.core:4.0.3]
>         at
> org.apache.karaf.features.internal.service.FeaturesServiceImpl.doProvision(FeaturesServiceImpl.java:1079)[7:org.apache.karaf.features.core:4.0.3]
>         at
> org.apache.karaf.features.internal.service.FeaturesServiceImpl$1.call(FeaturesServiceImpl.java:975)[7:org.apache.karaf.features.core:4.0.3]
>         at 
> java.util.concurrent.FutureTask.run(FutureTask.java:266)[:1.8.0_65]
>         at
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)[:1.8.0_65]
>         at
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)[:1.8.0_65]
>         at java.lang.Thread.run(Thread.java:745)[:1.8.0_65]
> 
> 
> Le 11.01.2016 19:54, David Jencks a écrit :
>> Well, you got farther anyway :-)  I don’t yet see what’s wrong.  Could
>> you supply the generated component xml and the ComponentException
>> stack trace?
>> 
>> With bnd 3+ you don’t (shouldn’t?) need to specify
>> (service=FileReader.class) as now bnd can analyze the generic
>> method/field signature to infer the service type.
>> 
>> thanks
>> david jencks
>>> On Jan 11, 2016, at 9:56 AM, ben@petinou.fr wrote:
>>> 
>>> Thanks David,
>>> 
>>> I tried that by get an error on karaf startup:
>>> cannot register Component 
>>> org.osgi.service.component.ComponentException: Component 
>>> FileReaderFactory validation failed: Field value type must not be set 
>>> for unary field references.
>>> 
>>> My class looks like this:
>>> 
>>> @Component
>>> public class FileReaderFactory implements ReaderManager {
>>>    @Reference(service = FileReader.class)
>>>    private List<FileReader> availableServices;
>>> 
>>>    @Override
>>>    public Data readFile(Path filePath) throws IOException {
>>>        for (FileReader reader : availableServices) {
>>>            if (reader.isFormatSupported(filePath)) {
>>>                return reader.readFile(filePath);
>>>            }
>>>        }
>>>        return null;
>>>    }
>>> 
>>>    @Override
>>>    public boolean isFormatSupported(Path filePath) throws IOException 
>>> {
>>>        for (FileReader reader : availableServices) {
>>>            if (reader.isFormatSupported(filePath)) {
>>>                return true;
>>>            }
>>>        }
>>>        return false;
>>>    }
>>> }
>>> 
>>> Le 11.01.2016 18:47, David Jencks a écrit :
>>>> Well, you need cmpn 6 for the ds 1.3 annotations (in particular
>>>> @Reference applicable to a field).  I thought this was on maven
>>>> central but haven’t looked.  If necessary you can get it from the 
>>>> OSGI
>>>> site.
>>>> david jencks
>>>>> On Jan 11, 2016, at 12:35 AM, ben@petinou.fr wrote:
>>>>> Hi everyone!
>>>>> I asked a question on stackoverflow regarding the use of 
>>>>> Declarative Services in Karaf to manage multiple instances of a 
>>>>> service, provided by different implementations of such a service.
>>>>> The question is explained in details here:
>>>>> http://stackoverflow.com/questions/34706041/how-to-manage-several-service-instances-in-declarative-services
>>>>> I received and answer telling me that using the @reference 
>>>>> annotation on the list storing the services would solve my problem. 
>>>>> For this, I would need to use DS 1.3.
>>>>> I thus asked on Karaf users mailing list what was the version of 
>>>>> Felix SCR provided with Karaf 4.0.3 
>>>>> (http://mail-archives.apache.org/mod_mbox/karaf-user/201601.mbox/%3C8dbfa59508d5769609e2c78c0210c7aa%40petinou.fr%3E)

>>>>> and was told it was Felix SCR 2.0.2, which supports DS 1.3. So far 
>>>>> so good.
>>>>> I was also kindly advised to ask this kind of questions here. So 
>>>>> here I am :-)
>>>>> Following the answer on stackoverflow, I tried to add the 
>>>>> @reference annotation to my service list like this:
>>>>> @Reference(service = FileReader.class)
>>>>> private List<FileReader> availableServices = new ArrayList<>();
>>>>> But it does not compile: FileReaderFactory.java:[37,5] annotation 
>>>>> type not applicable to this kind of declaration
>>>>> My project has a dependency on:
>>>>> <dependency>
>>>>>   <groupId>org.osgi</groupId>
>>>>>   <artifactId>org.osgi.compendium</artifactId>
>>>>>   <version>5.0.0</version>
>>>>>   <scope>provided</scope>
>>>>> </dependency>
>>>>> which seems to be the latest version available.
>>>>> I thus tried the "older way" by using explicit bind/unbind methods 
>>>>> like this:
>>>>>   @Reference(service = FileReader.class, unbind = "removeService")
>>>>>   public void addService(final FileReader serviceToAdd) {
>>>>>       System.out.println("FileReaderFactory.addService");
>>>>>       availableServices.add(serviceToAdd);
>>>>>       System.out.println(availableServices);
>>>>>   }
>>>>>   public void removeService(final FileReader serviceToRemove) {
>>>>>       System.out.println("FileReaderFactory.removeService");
>>>>>       availableServices.remove(serviceToRemove);
>>>>>       System.out.println(availableServices);
>>>>>   }
>>>>> If I have two implementations available, say TxtFileReader and 
>>>>> XmlFileReader, only the first one is added to the list. The status 
>>>>> of the second service (using scr:detail command) is "null".
>>>>> What am I missing?
>>>>> Kind regards,
>>>>> Ben

Mime
View raw message