karaf-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Paul Spencerx <p...@intekon.com>
Subject Re: Question about @Reference Karaf Command annotation
Date Thu, 16 Jul 2020 13:52:44 GMT
Alex,
I have created the following Jira.  Please note the Jira describes the behavior and references
this thread.  You may add information regarding the suspected root cause.

  https://issues.apache.org/jira/browse/KARAF-6790

Paul Spencer

> On Jul 16, 2020, at 8:50 AM, Alex Soto <alex.soto@envieta.com> wrote:
> 
> I also believe there is a bug here; I had pasted in a previous post the part of the code
I suspect is at fault.
> 
> Best regards,
> Alex soto
> 
> 
> 
> 
>> On Jul 16, 2020, at 6:26 AM, João Assunção <joao.assuncao@exploitsys.com>
wrote:
>> 
>> Paul,
>> you are right. I think there is a bug in the implementation of SingleServiceTracker
used to bind service references in commands.
>> The filter is used for the listener but is ignored when retrieving the serviceReference.
>> 
>> For example:
>> If the command starts and the services are available, it will use the first service
matching the class and ignore the filter.
>> If the command starts and no service is available, the listener will be called when
one service matches the filter. When one matches, SingleServiceTracker.findMatchingReference
will be called and the filter is ignored.
>> 
>> 
>> 
>> João Assunção
>> 
>> Email: joao.assuncao@exploitsys.com
>> Mobile: +351 916968984
>> Phone: +351 211933149
>> Web: www.exploitsys.com
>> 
>> 
>> 
>> 
>> On Thu, Jul 16, 2020 at 1:42 AM Paul Spencer <paulspencer@mindspring.com> wrote:
>> Martin,
>> Parenthesis in the @Reference, org.apache.karaf.shell.api.action.lifecycle.Reference,
for the Command did not change the results, this the wrong service was returned.  Parenthesis
are required for the @Reference,org.osgi.service.component.annotations.Reference, in the @Component.
>> 
>> Details below.
>> 
>> ***
>> * From command that uses the RedColor service
>> *  Parenthesis did not return the correct ColorService.
>> ***
>> import org.apache.karaf.shell.api.action.Action;
>> import org.apache.karaf.shell.api.action.Command;
>> import org.apache.karaf.shell.api.action.lifecycle.Reference;
>> import org.apache.karaf.shell.api.action.lifecycle.Service;
>> 
>> import com.example.service.ColorService;
>> 
>> @Service
>> @Command(scope = "color", name = "get-red", description = "Get Red Service")
>> public class DisplayRedServiceCommand implements Action {
>> 
>>         @Reference(filter = "(color=red)")
>>         private ColorService colorService;
>> 
>> ***
>> * Output from Command that get a RedColor service
>> ***
>> karaf@root()> color:get-red
>> Color = BLUE
>> 
>> ***
>> * Component the defines the RedColor service
>> ***
>> import org.osgi.service.component.annotations.Activate;
>> import org.osgi.service.component.annotations.Component;
>> import org.osgi.service.component.annotations.Deactivate;
>> import org.osgi.service.component.annotations.Modified;
>> import org.slf4j.Logger;
>> import org.slf4j.LoggerFactory;
>> 
>> import com.example.service.ColorService;
>> 
>> @Component(immediate = true, property = "color=red")
>> public class RedColorService implements ColorService {
>>         private final Logger log = LoggerFactory.getLogger(getClass());
>> 
>> ***
>> * Component that uses the RedColor Service
>> ***
>> import org.osgi.service.component.annotations.Activate;
>> import org.osgi.service.component.annotations.Component;
>> import org.osgi.service.component.annotations.Deactivate;
>> import org.osgi.service.component.annotations.Modified;
>> import org.osgi.service.component.annotations.Reference;
>> import org.slf4j.Logger;
>> import org.slf4j.LoggerFactory;
>> 
>> import com.example.service.ColorService;
>> import com.example.service.GenericColorService;
>> 
>> @Component(immediate = true, property = "color=all")
>> public class AllColorService implements GenericColorService {
>>         private final Logger log = LoggerFactory.getLogger(getClass());
>> 
>>         @Reference(target = "(color=red)")
>>         private ColorService redColorService;
>> 
>>         @Reference(target = "(color=green)")
>>         private ColorService greenColorService;
>>         @Reference(target = "(color=blue)")
>>         private ColorService blueColorService;
>> 
>>         @Override
>>         public String getColor() {
>>                 StringBuffer colors = new StringBuffer();
>>                 colors.append(redColorService.getColor());
>>                 colors.append(", ");
>>                 colors.append(greenColorService.getColor());
>>                 colors.append(", ");
>>                 colors.append(blueColorService.getColor());
>>                 return colors.toString();
>>         }
>> 
>> ***
>> * Command that get a two color service
>> ***
>> import org.apache.karaf.shell.api.action.Action;
>> import org.apache.karaf.shell.api.action.Command;
>> import org.apache.karaf.shell.api.action.lifecycle.Reference;
>> import org.apache.karaf.shell.api.action.lifecycle.Service;
>> 
>> import com.example.secondService.TwoColorService;
>> 
>> @Service
>> @Command(scope = "yellow", name = "yellow", description = "Get Yellow Service")
>> public class DisplayYellowServiceCommand implements Action {
>> 
>>         @Reference
>>         private TwoColorService colorService;
>> 
>>         @Override
>>         public Object execute() throws Exception {
>>                 System.out.println("Color = " + colorService.getColor());
>>                 return null;
>>         }
>> 
>> ***
>> * Output from Command that get a two color service
>> ***
>> karaf@root()> yellow:yellow
>> Color = RED, GREEN
>> 
>> 
>> ***
>> * Component that produces a two color service
>> ***
>> import org.osgi.service.component.annotations.Activate;
>> import org.osgi.service.component.annotations.Component;
>> import org.osgi.service.component.annotations.Deactivate;
>> import org.osgi.service.component.annotations.Modified;
>> import org.osgi.service.component.annotations.Reference;
>> import org.slf4j.Logger;
>> import org.slf4j.LoggerFactory;
>> 
>> import com.example.secondService.TwoColorService;
>> import com.example.service.ColorService;
>> 
>> @Component(immediate = true, property = "2color=yellow")
>> public class YellowColorService implements TwoColorService {
>>         private final Logger log = LoggerFactory.getLogger(getClass());
>> 
>>         @Reference(target = "(color=red)")
>>         private ColorService redColorService;
>>         @Reference(target = "(color=green)")
>>         private ColorService greenColorService;
>> 
>>         @Override
>>         public String getColor() {
>>                 StringBuffer colors = new StringBuffer();
>>                 colors.append(redColorService.getColor());
>>                 colors.append(", ");
>>                 colors.append(greenColorService.getColor());
>>                 return colors.toString();
>>         }
>> 
>> Paul Spencer
>> 
>> 
>> > On Jul 15, 2020, at 3:12 PM, Martin Lichtin <lichtin@yahoo.com> wrote:
>> > 
>> > Yes that should work. You need the parenthesis.
>> > The code is doing something like
>> > 
>> >                 String filterString = '(' + Constants.OBJECTCLASS + '=' + clazz.getName()
+ ')';
>> >                 if (filter != null && !filter.isEmpty()) {
>> >                     filterString = "(&" + filterString + filter + ')';
>> >                 }
>> > 
>> > On 15.07.2020 18:06, João Assunção wrote:
>> >> Hello all,
>> >> 
>> >> Have you tried to use an LDAP filter expression?  Instead of *color=red*
try *(color=red). *(I haven't tried this myself)
>> >> 
>> >> João Assunção
>> >> 
>> >> Email: joao.assuncao@exploitsys.com <mailto:joao.assuncao@exploitsys.com>
>> >> Mobile: +351 916968984
>> >> Phone: +351 211933149
>> >> Web: www.exploitsys.com <http://www.exploitsys.com>
>> >> 
>> >> 
>> >> 
>> >> 
>> >> On Mon, Jul 13, 2020 at 6:33 PM Paul Spencerx <paul@intekon.com <mailto:paul@intekon.com>>
wrote:
>> >> 
>> >>    JB,
>> >>    What is the status of your checking?
>> >> 
>> >>    @Reference for commands is not working for me either.  I have included
related code and output from Karaf below.
>> >> 
>> >>    ***
>> >>    * Testing commands
>> >>    ***
>> >>    karaf@root()> color --help
>> >>    SUBSHELL
>> >>            color
>> >> 
>> >>    COMMANDS
>> >>        color:get-any   Get any Service
>> >>        color:get-blue  Get Blue Service
>> >>        color:get-green Get Green Service
>> >>        color:get-red   Get Red Service
>> >>    karaf@root()> color:get-red
>> >>    Color = BLUE
>> >>    karaf@root()> color:get-red
>> >>    Color = BLUE
>> >>    karaf@root()> color:get-red
>> >>    Color = BLUE
>> >>    karaf@root()> color:get-any
>> >>    Color = BLUE
>> >>    karaf@root()> color:get-green
>> >>    Color = BLUE
>> >>    karaf@root()>
>> >> 
>> >>    ***
>> >>    * Available Color Services
>> >>    ***
>> >>    karaf@root()> services -p  165
>> >> 
>> >>    Karaf Service sandbox (165) provides:
>> >>    -------------------------------------
>> >>    color = blue
>> >>    component.id <http://component.id> = 9
>> >>    component.name <http://component.name> = com.example.service.internal.BlueColorService
>> >>    objectClass = [com.example.service.ColorService]
>> >>    service.bundleid = 165
>> >>    service.id <http://service.id> = 193
>> >>    service.scope = bundle
>> >>    ----
>> >>    color = green
>> >>    component.id <http://component.id> = 10
>> >>    component.name <http://component.name> = com.example.service.internal.GreenColorService
>> >>    objectClass = [com.example.service.ColorService]
>> >>    service.bundleid = 165
>> >>    service.id <http://service.id> = 194
>> >>    service.scope = bundle
>> >>    ----
>> >>    color = red
>> >>    component.id <http://component.id> = 11
>> >>    component.name <http://component.name> = com.example.service.internal.RedColorService
>> >>    objectClass = [com.example.service.ColorService]
>> >>    service.bundleid = 165
>> >>    service.id <http://service.id> = 195
>> >>    service.scope = bundle
>> >>    karaf@root()>
>> >> 
>> >>    ***
>> >>    * Example command source code
>> >>    ***
>> >>    package com.example.command.internal;
>> >> 
>> >>    import org.apache.karaf.shell.api.action.Action;
>> >>    import org.apache.karaf.shell.api.action.Command;
>> >>    import org.apache.karaf.shell.api.action.lifecycle.Reference;
>> >>    import org.apache.karaf.shell.api.action.lifecycle.Service;
>> >> 
>> >>    import com.example.service.ColorService;
>> >> 
>> >>    @Service
>> >>    @Command(scope = "color", name = "get-red", description = "Get Red Service")
>> >>    public class DisplayRedServiceCommand implements Action {
>> >> 
>> >>            @Reference(filter = "color=red")
>> >>            private ColorService colorService;
>> >> 
>> >>            @Override
>> >>            public Object execute() throws Exception {
>> >>                    System.out.println("Color = " + colorService.getColor());
>> >>                    return null;
>> >>            }
>> >> 
>> >>    }
>> >> 
>> >>    ***
>> >>    * Example Service source code
>> >>    ***
>> >>    package com.example.service.internal;
>> >> 
>> >>    import org.osgi.service.component.annotations.Component;
>> >> 
>> >>    import com.example.service.ColorService;
>> >> 
>> >>    @Component(immediate = true, property = "color=red")
>> >>    public class RedColorService implements ColorService {
>> >> 
>> >>            @Override
>> >>            public String getColor() {
>> >>                    return "RED";
>> >>            }
>> >> 
>> >>    }
>> >> 
>> >> 
>> >>    Paul Spencer
>> >> 
>> >> 
>> >>    > On Mar 12, 2020, at 9:41 AM, Alex Soto <alex.soto@envieta.com
<mailto:alex.soto@envieta.com>> wrote:
>> >>    >
>> >>    > Just to clarify, when I say it does not work, I mean that the injected
service is not the correct one matching the filter expression.
>> >>    >
>> >>    > Best regards,
>> >>    > Alex soto
>> >>    >
>> >>    >
>> >>    >
>> >>    >
>> >>    >> On Mar 12, 2020, at 9:24 AM, Jean-Baptiste Onofre <jb@nanthrax.net
<mailto:jb@nanthrax.net>> wrote:
>> >>    >>
>> >>    >> Hi,
>> >>    >>
>> >>    >> Let me check, but AFAIR, I have a test about that and it seems
to work.
>> >>    >>
>> >>    >> I will create a Jira to double check.
>> >>    >>
>> >>    >> Regards
>> >>    >> JB
>> >>    >>
>> >>    >>> Le 12 mars 2020 à 14:23, Alex Soto <alex.soto@envieta.com
<mailto:alex.soto@envieta.com>> a écrit :
>> >>    >>>
>> >>    >>> I see, but it is not working for me…
>> >>    >>>
>> >>    >>> The PR  does not update org.apache.karaf.shell.impl.action.command.ManagerImpl#instantiate,
shouldn’t this method be updated also to inject the appropriate service when the command
is instantiated? (See code fragment I pasted earlier)
>> >>    >>>
>> >>    >>>
>> >>    >>> Best regards,
>> >>    >>> Alex soto
>> >>    >>>
>> >>    >>>
>> >>    >>>
>> >>    >>>
>> >>    >>>> On Mar 12, 2020, at 9:07 AM, Jean-Baptiste Onofre <jb@nanthrax.net
<mailto:jb@nanthrax.net>> wrote:
>> >>    >>>>
>> >>    >>>> Hi Alex,
>> >>    >>>>
>> >>    >>>> You can find the change I did about that here:
>> >>    >>>>
>> >>    >>>> https://github.com/apache/karaf/pull/992
>> >>    >>>>
>> >>    >>>> Regards
>> >>    >>>> JB
>> >>    >>>>
>> >>    >>>>> Le 12 mars 2020 à 14:02, Alex Soto <alex.soto@envieta.com
<mailto:alex.soto@envieta.com>> a écrit :
>> >>    >>>>>
>> >>    >>>>> Thanks, JB
>> >>    >>>>>
>> >>    >>>>> But it doesn’t seem to work for Karaf 4.2.8.
>> >>    >>>>> I am not  familiar with the internals of Karaf code,
but I spotted the following in org.apache.karaf.shell.impl.action.command.ManagerImpl.instantiate
of  org.apache.karaf.shell.core-4.2.8.jar:
>> >>    >>>>>
>> >>    >>>>>           Reference ref = field.getAnnotation(Reference.class);
>> >>    >>>>>                 if (ref != null) {
>> >>    >>>>>                     GenericType type = new GenericType(field.getGenericType());
>> >>    >>>>>                     Object value;
>> >>    >>>>>                     if (type.getRawClass() == List.class)
{
>> >>    >>>>>                         Set<Object> set =
new HashSet<>();
>> >>    >>>>>  set.addAll(registry.getServices(type.getActualTypeArgument(0).getRawClass()));
>> >>    >>>>>                         if (registry != this.dependencies)
{
>> >>    >>>>>  set.addAll(this.dependencies.getServices(type.getActualTypeArgument(0).getRawClass()));
>> >>    >>>>>                         }
>> >>    >>>>>                         value = new ArrayList<>(set);
>> >>    >>>>>                     } else {
>> >>    >>>>>                         value = registry.getService(type.getRawClass());
>> >>    >>>>>                         if (value == null &&
registry != this.dependencies) {
>> >>    >>>>>                             value = this.dependencies.getService(type.getRawClass());
>> >>    >>>>>                         }
>> >>    >>>>>                     }
>> >>    >>>>>                     if (!allowCustomServices &&
value == null && !ref.optional()) {
>> >>    >>>>>                         throw new IllegalStateException("No
service matching " + field.getType().getName());
>> >>    >>>>>                     }
>> >>    >>>>>  field.setAccessible(true);
>> >>    >>>>>                     field.set(instance, value);
>> >>    >>>>>                 }
>> >>    >>>>>
>> >>    >>>>> Maybe this is not the relevant piece of code, but
I do not see that the filter attribute is being used to look up the service.
>> >>    >>>>>
>> >>    >>>>>
>> >>    >>>>> Best regards,
>> >>    >>>>> Alex soto
>> >>    >>>>>
>> >>    >>>>>
>> >>    >>>>>
>> >>    >>>>>
>> >>    >>>>>> On Mar 12, 2020, at 12:50 AM, Jean-Baptiste
Onofre <jb@nanthrax.net <mailto:jb@nanthrax.net>> wrote:
>> >>    >>>>>>
>> >>    >>>>>> Hi,
>> >>    >>>>>>
>> >>    >>>>>> Yes, it’s to "select" the service you want
to use.
>> >>    >>>>>>
>> >>    >>>>>> I did the change because previously it wasn’t
possible to select, meaning that if you had several services (with the same interface) available,
it took the first one.
>> >>    >>>>>>
>> >>    >>>>>> Now, you can specify the LDIF filter to select
the exact service you want to inject.
>> >>    >>>>>>
>> >>    >>>>>> Regards
>> >>    >>>>>> JB
>> >>    >>>>>>
>> >>    >>>>>>> Le 11 mars 2020 à 20:03, Alex Soto <alex.soto@envieta.com
<mailto:alex.soto@envieta.com>> a écrit :
>> >>    >>>>>>>
>> >>    >>>>>>> Is the filter attribute in annotation org.apache.karaf.shell.api.action.lifecycle.Reference
used to filter the injected service on Service attributes?
>> >>    >>>>>>>
>> >>    >>>>>>> Best regards,
>> >>    >>>>>>> Alex soto
>> >>    >>>>>>>
>> >>    >>>>>>>
>> >>    >>>>>>>
>> >>    >>>>>>>
>> >>    >>>>>>
>> >>    >>>>>
>> >>    >>>>
>> >>    >>>
>> >>    >>
>> >>    >
>> >> 
>> 
> 


Mime
View raw message