0

I am trying to get bind/unbind methods called on a DS component. I've reduced it to the simplest example that doesn't work.

If I remove the @Reference on the bind method then the test is successful. Obviously the log statements don't get called. Otherwise it fails on the AssertNotNull.

Any suggestions on what I'm doing wrong? What is the right way to add bind/unbind methods to a component?

Updated code to show correct approach.

Interface

public interface Foo {
    public abstract String bar();
}

Class

@Component(immediate = true, enabled = true, service = Foo.class, scope = ServiceScope.SINGLETON)
public class FooImpl implements Foo {
private final static Logger logger = LoggerFactory.getLogger(FooImpl.class);

@Override
public String bar() {
    return "bar";
}

@Activate
public synchronized void bind() {
    logger.debug(String.format("bind called for %s", this.getClass().getName()));
}

@Deactivate
public synchronized void unbind(Foo service) {
    logger.debug(String.format("unbind called for %s", this.getClass().getName()));
}
}

Generated component definition

<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.3.0" activate="bindFoo" deactivate="unbindFoo" enabled="true" immediate="true" name="com.vogelware.experiment.FooImpl">
   <service scope="singleton">
      <provide interface="com.vogelware.experiment.Foo"/>
   </service>
   <implementation class="com.vogelware.experiment.FooImpl"/>
</scr:component>

Test class

class FooTest {
    @Test
    void test() throws InterruptedException {
        ServiceTracker<Foo, Foo> testTracker = new ServiceTracker<Foo, Foo>(Activator.getContext(), Foo.class, null);
        testTracker.open();
        testTracker.waitForService(500);
        Foo user = testTracker.getService();
        testTracker.close();
        assertNotNull(user);  <= fails here
    }
}
Timothy Vogel
  • 1,363
  • 2
  • 21
  • 39

2 Answers2

2

Your component is trying to use itself as a dependency. Thus you have an unsolvable circular reference. Your component cannot be satisfied (and thus registered as a Foo service) until its dependency on a Foo service (the @Reference) can be met.

BJ Hargrave
  • 9,324
  • 1
  • 19
  • 27
0

The answer to my question is that in the 1.3 spec, use @Activate and @Deactivate. I've modified the original question to show the solution in code.

Check out http://blog.vogella.com/2016/06/21/getting-started-with-osgi-declarative-services/ for more details.

Timothy Vogel
  • 1,363
  • 2
  • 21
  • 39