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 <[email protected]> 
> 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: [email protected] <mailto:[email protected]>
> Mobile: +351 916968984
> Phone: +351 211933149
> Web: www.exploitsys.com <http://www.exploitsys.com/>
> 
> 
> 
> 
> On Thu, Jul 16, 2020 at 1:42 AM Paul Spencer <[email protected] 
> <mailto:[email protected]>> 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 <[email protected] 
> > <mailto:[email protected]>> 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: [email protected] <mailto:[email protected]> 
> >> <mailto:[email protected] <mailto:[email protected]>>
> >> Mobile: +351 916968984
> >> Phone: +351 211933149
> >> Web: www.exploitsys.com <http://www.exploitsys.com/> 
> >> <http://www.exploitsys.com <http://www.exploitsys.com/>>
> >> 
> >> 
> >> 
> >> 
> >> On Mon, Jul 13, 2020 at 6:33 PM Paul Spencerx <[email protected] 
> >> <mailto:[email protected]> <mailto:[email protected] 
> >> <mailto:[email protected]>>> 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/> <http://component.id 
> >> <http://component.id/>> = 9
> >>    component.name <http://component.name/> <http://component.name 
> >> <http://component.name/>> = com.example.service.internal.BlueColorService
> >>    objectClass = [com.example.service.ColorService]
> >>    service.bundleid = 165
> >>    service.id <http://service.id/> <http://service.id 
> >> <http://service.id/>> = 193
> >>    service.scope = bundle
> >>    ----
> >>    color = green
> >>    component.id <http://component.id/> <http://component.id 
> >> <http://component.id/>> = 10
> >>    component.name <http://component.name/> <http://component.name 
> >> <http://component.name/>> = com.example.service.internal.GreenColorService
> >>    objectClass = [com.example.service.ColorService]
> >>    service.bundleid = 165
> >>    service.id <http://service.id/> <http://service.id 
> >> <http://service.id/>> = 194
> >>    service.scope = bundle
> >>    ----
> >>    color = red
> >>    component.id <http://component.id/> <http://component.id 
> >> <http://component.id/>> = 11
> >>    component.name <http://component.name/> <http://component.name 
> >> <http://component.name/>> = com.example.service.internal.RedColorService
> >>    objectClass = [com.example.service.ColorService]
> >>    service.bundleid = 165
> >>    service.id <http://service.id/> <http://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 <[email protected] 
> >> <mailto:[email protected]> <mailto:[email protected] 
> >> <mailto:[email protected]>>> 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 <[email protected] 
> >> <mailto:[email protected]> <mailto:[email protected] 
> >> <mailto:[email protected]>>> 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 <[email protected] 
> >> <mailto:[email protected]> <mailto:[email protected] 
> >> <mailto:[email protected]>>> 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 
> >> <[email protected] <mailto:[email protected]> <mailto:[email protected] 
> >> <mailto:[email protected]>>> wrote:
> >>    >>>>
> >>    >>>> Hi Alex,
> >>    >>>>
> >>    >>>> You can find the change I did about that here:
> >>    >>>>
> >>    >>>> https://github.com/apache/karaf/pull/992 
> >> <https://github.com/apache/karaf/pull/992>
> >>    >>>>
> >>    >>>> Regards
> >>    >>>> JB
> >>    >>>>
> >>    >>>>> Le 12 mars 2020 à 14:02, Alex Soto <[email protected] 
> >> <mailto:[email protected]> <mailto:[email protected] 
> >> <mailto:[email protected]>>> 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 
> >> <[email protected] <mailto:[email protected]> <mailto:[email protected] 
> >> <mailto:[email protected]>>> 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 <[email protected] 
> >> <mailto:[email protected]> <mailto:[email protected] 
> >> <mailto:[email protected]>>> 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
> >>    >>>>>>>
> >>    >>>>>>>
> >>    >>>>>>>
> >>    >>>>>>>
> >>    >>>>>>
> >>    >>>>>
> >>    >>>>
> >>    >>>
> >>    >>
> >>    >
> >> 
> 

Reply via email to