Resolve NullPointerException when calling service that has not yet been loaded

Technical Blogs September 4, 2017 By Dániel Jávorszky Staff

Sometimes, when creating a module, we may run into a situation where the service we're trying to use has not been properly loaded and tracked by OSGi yet. In such cases, the result of our service call will be a NullPointerException coming from the *ServiceUtil class, for example:

java.lang.NullPointerException
    at com.liferay.dynamic.data.mapping.service.DDMStructureLocalServiceUtil.getStructures(DDMStructureLocalServiceUtil.java:910)

Checking the line from where its thrown, we see that the only way for a NullPointerException to occur is if getService() returns null.

getService() calls the serviceTracker, which, according to its javadoc, returns null if its not tracking any service objects for that service.

Such a situation can arise if we're trying to call the service during the global.startup.events phase for example - Where OSGi is still working on registering all the services that are being loaded.

Thankfully, there's a way to resolve this issue - add a ServiceDependencyListener.

A ServiceDependencyListener, once added with one or more services, will be called once all of the services have been properly loaded and tracked.

To register a ServiceDependencyListener, just add the below:

ServiceDependencyManager serviceDependencyManager = new ServiceDependencyManager();

serviceDependencyManager.addServiceDependencyListener(new ServiceDependencyListener() {

    @Override
    public void dependenciesFulfilled() {
        _log.info("Dependencies fulfilled.");
        doWhatNeedsToBeDone();
    }

    @Override
    public void destroy() {
        // ignore
    }

});

Registry registry = RegistryUtil.getRegistry();

Filter ddmFilter = registry.getFilter("(&(objectClass=" + DDMStructureService.class.getName() + "))");

serviceDependencyManager.registerDependencies(ddmFilter);

The above is quite straightforward: Create a ServiceDependencyManager, add a new Listener with its two required methods that will be called once the dependencies are fulfilled and once the listener is no longer needed, then get the registry, construct a filter and register it as a dependency.

Hope this helps,

Daniel

Showing 1 result.