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