How to add an observer to a nano service

Binoculars, van Gogh

Registering observers to nano services is quite common.

Prerequisite for the tutorial

You should have read these tutorials beforehand:
Package initialization
How to start a simple target

The short way

To make registration as easy as possible, another service has been created: the RecordHelper. Enter the dependency in the ServiceStarter.

public void getDependencies(@NotNull final IServiceDependencyList aDependencyList)
{
    aDependencyList.add(IRecordHelper.class);
}

In the target:

private boolean asyncStartTarget(@NotNull final CEnvelope aEnvelope,
                                 @NotNull final CRecord aRecord) throws CException
{
    mDependencies.getRecordHelper()
                 .addObserver(CRecordNotifyRemoteNodeAdded.class,
                              this,
                              true);
    aEnvelope.setResultSuccess();
    return true;
}

The long way

Add the nano service registry as a dependency to the service starter. As a filter, we need to enter the namespace where the desired nano service is registered.

public void getDependencies(@NotNull final IServiceDependencyList aDependencyList)
{
    aDependencyList.add(INanoServiceRegistry.class,
                        "nid=SYSTEM");
}

In the ServiceStarter, the desired service is also fetched with filter.

@Override
public void start(@NotNull final IServiceRegistry aServiceRegistry) throws Exception
{
    if (mService == null)
    {
        mNanoServiceRegistry = aServiceRegistry.getServiceOrThrow(INanoServiceRegistry.class,
                                                                  "nid=SYSTEM");
        ...
    }
}

In the target, the observer is registered directly in the nano service registry.

private boolean asyncStartTarget(@NotNull final CEnvelope aEnvelope,
                                 @NotNull final CRecord aRecord) throws CException
{
    final INanoServiceRegistry nanoServiceRegistry = mDependencies.getNanoServiceRegistry();
    nanoServiceRegistry.addObserver(CRecordNotifyRemoteNodeAdded.class,
                                    getAddress(),
                                    false);

    aEnvelope.setResultSuccess();
    return true;
}

The disadvantage here is if you want to register multiple observers in different namespaces. You would then also have to enter multiple dependencies in the ServiceStarter and the Dependencies interface. However, this rarely happens.

Other ways

You could also enter dependencies to the respective namespaces. From the namespaces you get to the nano service registries, and there you can register the observers.

Or get the namespace registry, from the registry get the namespace, and from the namespace get the nano service registry.

Last but not least, you can use the namespace factory to have the namespace created only if it does not exist. Otherwise, the factory returns the existing namespace. And via the namespace we come back to the nano service registry.

Consume the messages

Add the message handler in the constructor:

addMessageHandler(CRecordNotifyRemoteNodeAdded.ID,
                  this::asyncNotifyRemoteNodeAdded);

After that you can receive this message every time the notification is triggered.

private boolean asyncNotifyRemoteNodeAdded(@NotNull final CEnvelope aEnvelope,
                                           @NotNull final CRecord aRecord) throws CException
{
    // do something
    aEnvelope.setResultSuccess();
    return true;
}