title: How to select an appropriate service implementation?
body: <p>I've created a service with multiple implementations, like so:</p>
  
  <pre><code>@ProviderType
  public interface MyService {
      public void printMessage();
  }
  
  @Component
  public class Foo implements MyService {
      public void printMessage() {
          System.out.println("foo");
      }
  }
  
  @Component
  public class Bar implements MyService {
      public void printMessage() {
          System.out.println("bar");
      }
  }
  </code></pre>
  
  <p>The real implementations are obviously a bit more complex (I can't just make a single implementation where <code>printMessage</code> takes an argument!). The consumers of the service need to be able to select an appropriate implementation based on a property - for simplicity, we can assume I'm using the name of the implementation.</p>
  
  <p>The factory method used by the existing non-OSGi implementation is something like this:</p>
  
  <pre><code>public MyService getService(String property) {
      switch (property) {
          case "ham":
              return new Foo();
          case "spam":
              return new Bar();
      }
  }
  </code></pre>
  
  <p>The real implementation is, again, more complicated (it's based on a substring match of the <code>property</code> parameter). The simplest approach (for me) to convert this to OSGi would be to make this factory method into a static method of <code>MyService</code>, returning only the necessary filter string, and to make consumers take care of the fiddly bits with getting a BundleContext, then getting and ungetting the service:</p>
  
  <pre><code>public class MyConsumer {
      private BundleContext context;
  
      @Activate
      public void activate(BundleContext context) {
          this.context = context;
      }
  
      public void doStuff() {
          Collection&lt;ServiceReference&lt;MyService&gt;&gt; refs = context.getServiceReferences(MyService.class, MyService.getService("ham"));
          ServiceReference&lt;MyService&gt; service = refs.iterator().next();
          context.getService(service).printMessage();
          context.ungetService(service);
      }
  </code></pre>
  
  <p><strong>Is there a better way to create a "factory" that returns "services", but doesn't require that the consumers deal with BundleContexts etc.?</strong></p>
  
  <p>I've found a couple approaches that won't <em>quite</em> work:</p>
  
  <ul>
  <li><code>@Reference(target = "ham")</code> (I know that syntax is wrong) allows me to select an implementation based on a property, but only at compile-time.</li>
  <li>A <code>ServiceFactory</code> allows different bundles to get different instances of the service, but not to specify implementation.</li>
  </ul>