I wrote my service faster than I planned, looking at my own tutorial, compiled it and everything looked fine.
And then I started testing it using atlas-run. (Suspense music ♪♫♫).
Boom..Null pointer Exception where the injected ActiveObjects component is used. Surely, ActiveObjects in not injected properly in the constructor of a service. Now, it makes sense because the service is probably initialized before the Active Objects plugin is loaded.
Backup plan (Plan B) - Get the ActiveObjects object suing ComponentManager.
ActiveObjects ao = ComponentManager.getOSGiComponentInstanceOfType(ActiveObjects.class);
In the run method, I initialized ActiveObjects for the first time as mentioned above and yes! I got a valid object. But then came across this error:
atlassian.activeobjects.osgi.ActiveObjectsServiceFactory] Could not find any active objects configurations for bundle org.apache.felix.framework.
Did you define an 'ao' module descriptor in your plugin?
Try adding this in your atlassian-plugin.xml file: <ao key='some-key' />
And this, in spite of having a valid definition in the atlassian-plugin.xml. Surely, something is not right.
Backup plan (Plan C) - Use the powers of Google, when yours is not working.
Google, now effectively crawling answers.atlassian.com, brought me a similar thread (hail Google!) where Stefan Chapuis stumbled up on a similar issue for mail handlers. And Wojciech Seliga had a brilliant workaround based on the reasoning - ActiveObjects can only be injected.
The workaround is pretty simple:
- Create you own component in the plugin using component plugin module.
<component key="jtricks-manager" name="J-Tricks Manager" public="true">
<interface>com.jtricks.manager.JTricksManager</interface>
</component> - Inject ActiveObjects in your component.
package com.jtricks.manager;
import com.atlassian.activeobjects.external.ActiveObjects;
public class JTricksManagerImpl implements JTricksManager{
private final ActiveObjects ao;
public JTricksManagerImpl(ActiveObjects ao) {
this.ao = ao;
}
@Override
public ActiveObjects getActiveObjects() {
return this.ao;
}
} - Get an instance of the component in the service's run method using ComponentManager
if (this.jTricksManager == null)
this.jTricksManager = ComponentAccessor.getOSGiComponentInstanceOfType(JTricksManager.class); - Retrieve the ActiveObjects object from the component
ActiveObjects ao = this.jTricksManager.getActiveObjects();
Hope this helps someone stumbling up on the same/similar issue. And if you know a better trick, or if it is working for you in some other way, please do comment.