Blueprint: how do I check if an optional dependency is satisfied?
Asked Answered
F

1

10

In blueprint.xml, I declare an optional dependency this way:

<reference id="RepositoryListener"
    interface="ru.focusmedia.odp.server.datastore.api.RepositoryListener"
    availability="optional" />

<bean id="Repository"
    class="ru.focusmedia.odp.server.datastore.jpa.repository.RepositoryImpl">
    <jpa:context property="entityManager" unitname="ODP_Server" />
    <tx:transaction method="*" value="Required" />
    <property name="repositoryListener" ref="RepositoryListener" />
</bean>

and in RepositoryImpl, I have

public void setRepositoryListener(RepositoryListener repositoryListener) {
    logger.info("Repository listener set");
    this.repositoryListener = repositoryListener;
}

This method is called by Blueprint even when there is no RepositoryListener service available, as expected. The problem is, how can I check later whether there is a service?

    if (repositoryListener != null) {
        repositoryListener.notifyDelete(node);
    } else {
        logger.warn("No repository listener set!");
    }

doesn't work, since repositoryListener isn't null, but a Blueprint proxy.

Foreground answered 29/5, 2012 at 6:25 Comment(1)
Limited knowledge on my part, but there is something called <reference-listener> that can be specified for <reference> and probably be linked to your Repository bean.Homosexual
B
17

There are three options.

  • Normally, if try and use the (missing) optional service, you'll get a five minute delay while blueprint waits for a backing service to appear, followed by a ServiceUnavailableException. So one option is to set a very short blueprint timeout, and catch the ServiceUnavailableException.
  • An arguably cleaner option is to use a reference listener to monitor the lifecycle of the service. This has the disadvantage of needing extra code.
  • The simplest - and therefore laziest - option of all is to use an optional reference list instead of an optional reference. If no satisfying services are present, the list will be empty. Of course, you'll have to think about what you want to happen if multiple satisfying services are present.

To set a shorter timeout, just add an attribute to your optional service reference:

<reference
    id="someReference"
    interface="org.some.service.ServiceInterface"
    availability="optional"
    timeout="100" />

To use a reference listener, you'd add something like the following to your blueprint xml (there's a more detailed example and discussion in chapter 6 of Enterprise OSGi in Action):

<reference
        id="someReference"
        interface="org.some.service.ServiceInterface">
        <reference-listener
            ref="someBean"
            bind-method="bind"
            unbind-method="unbind" />
    </reference>

The bind and unbind methods are called as your service appears and disappears (or as services get added and removed to your reference list, if you're using a reference list).

Using a reference list doesn't really need a code example - just use a <reference-list element and ensure your setter method takes a List.

Blessing answered 29/5, 2012 at 8:41 Comment(1)
Yes, I've thought of the third version as well. Probably the best option for me.Foreground

© 2022 - 2024 — McMap. All rights reserved.