You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@karaf.apache.org by be...@petinou.fr on 2016/01/11 09:35:17 UTC

How to manage several service instances with declarative services?

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

Re: How to manage several service instances with declarative services?

Posted by David Jencks <da...@yahoo.com.INVALID>.
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


Re: How to manage several service instances with declarative services?

Posted by be...@petinou.fr.
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

Re: How to manage several service instances with declarative services?

Posted by David Jencks <da...@yahoo.com.INVALID>.
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