Reputation: 1407
I'm developing an application with OSGi. Looking inside the OSGi compendium 6.0 (section 112.8.1) I've come across the declarative service; in particular I looked the following paragraph:
For a field, the defaults for the Reference annotation are:
- The name of the bind method or field is used for the name of the reference.
- 1:1 cardinality if the field is not a collection. 0..n cardinality if the field is a collection.
- Static reluctant policy if the field is not declared volatile. Dynamic reluctant policy if the field is declared volatile
- The requested service is the type of the field.
For example:
@Reference volatile Collection<LogService> log;
Now, I read from Neil Bartlett's OSGi in practice (section 11.10.2) that synchronization and concurrency of bind and unbind methods of Reference annotation
are a bit tricky (especially in dynamic policy scnearios). In particular, a thread-safe example of a reference of a service via annotation may be:
@Component( provide = MailboxListener.class, properties = { "service.ranking = 10"})
public class LogMailboxListener implements MailboxListener {
private final AtomicReference<Log> logRef = newAtomicReference <Log> () ;
public void messagesArrived ( String mboxName, Mailbox mbox, long [ ] ids ) {
Log log = logRef.get();
if (log != null )
log.log(Log.INFO, ids.length + "message(s) arrived in mailbox " + mboxName, null);
else
System.err.println("No log available!");
}
@Reference( service = Log.class, dynamic = true, optional = true )
public void setLog(Log log) {
logRef.set(log);
}
public void unsetLog(Log log) {
logRef.compareAndSet(log, null);
}
}
I think I grasped from the book why there the dynamic policy needs this adjustements from the multi-threading scenario. My question is: if the reference annotation were on a field (declarative service 1.3) how could I achieve thread-safety? Only by defining the reference as "volatile" (as compendium suggest)? Or there is some tricky part that will create problems in the application?
Thanks for any kind reply
Upvotes: 1
Views: 1785
Reputation: 9384
When you use a dynamic policy reference on a field, the field must be volatile. In your example, each time the set of LogServices change, a new collection is injected into the field. So this will be safe since if your code is iterating over the old collection, the old collection is unaltered. When you code goes back to the log field, it will see the new collection.
So all you need to do is declare the field volatile and do not store the field value somewhere else since the field will be updated to a new collection whenever the set of bound services changes.
Upvotes: 4