Dependency Injection in Service constructor not working?

Deleted user June 21, 2018

In my JIRA plugin, I want to implement a service (which can be scheduled via the Services admin interface) which shall receive required objects via constructor injection, e.g. like this:

@ExportAsService
public class MyPluginService extends AbstractService {

private final SomeHelloWorldInterface helloWorld;

@Inject
public MyPluginService(final SomeHelloWorldInterface helloWorld) {
this.helloWorld = helloWorld;
}

An implementation is also present within my plugin:

@JiraComponent
public class SomeHelloWorldClass implements SomeHelloWorldInterface {

@Override
public String sayHelloWorld() {
return "Hello World!";
}

}

Unfortunately, when trying to activate this as a Service, I receive this error:

  • Error adding service: org.picocontainer.injectors.AbstractInjector$UnsatisfiableDependenciesException: com.....impl.MyPluginService has unsatisfied dependency 'interface com.....api.SomeHelloWorldInterface' for constructor 'public com.....impl.MyPluginService(com....api.SomeHelloWorldInterface)' from org.picocontainer.DefaultPicoContainer@7ba6a405:1<[Immutable]:com.atlassian.jira.component.CachingMutablePicoContainer@466051b1.

For whatever reason, the dependency from the Service to the (plugin-internal) component cannot be resolved. I tried several different annotations (e.g. @Autowired), but to no avail.

Any idea what I am doing wrong here? Or does @ExportAsService block plugin-internal dependency resolution?

3 answers

1 accepted

1 vote
Answer accepted
Deleted user July 5, 2018

I found the "solution", or at least the root cause, myself. 

If one uses the "Services" functionality of JIRA, the given class name is instantiated within the Pico IoC container context only. This means, no Spring resolution available.

To access and autowire a component scanned by Spring within your service's constructor, use this:

ComponentAccessor.getOSGiComponentInstanceOfType(SomeHelloWorldInterface.class);

Standard JIRA components can, of course, be autowired as usual (as they are available via the Pico container).

This only took one week to be discovered and understood. I'd appreciate if this was documented e.g. in the Javadoc of AbstractService.

1 vote
Alexey Matveev
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 21, 2018

Try to do like this

@ExportAsService
@Named

public class MyPluginService extends AbstractService {

private final SomeHelloWorldInterface helloWorld;

@Inject
public MyPluginService(final SomeHelloWorldInterface helloWorld) {
this.helloWorld = helloWorld;
}

 

@Named
public class SomeHelloWorldClass implements SomeHelloWorldInterface {

@Override
public String sayHelloWorld() {
return "Hello World!";
}

}
Deleted user June 21, 2018

Thanks for your suggestion! Unfortunately, exactly the same effect.

Nikhil_Tyagi May 6, 2020

This works. Thanks @Alexey Matveev  you saved me so much time. Cheers!

0 votes
Giorgia Fineschi January 15, 2021

Hi everyone, I'm writing a custom Jira plugin of type Service.

I have

@Named
@ExportAsService
public class ENGSLAService extends AbstractService {

@JiraImport
private JqlQueryParser jqlQueryParser;

@JiraImport
private SearchService searchService;

private InsightReader insightReader;

@Inject
public ENGSLAService(JqlQueryParser jqlQueryParser, SearchService searchService) {

this.jqlQueryParser = jqlQueryParser;
this.searchService = searchService;
this.insightReader = ComponentAccessor.getOSGiComponentInstanceOfType(InsightReader.class);
log.warn("insightReader is " + insightReader);
}

...

}
@JiraComponent
public class InsightReader {

@JiraImport
private ObjectFacade objectFacade;
@JiraImport
private IQLFacade iqlFacade;

...

}

Basically I don't know how I can initialize a InsightReader's object inside my ENGSLAService constructor. I tryied different arrangements with annotations and non-empty constructor in InsightReader's class but nothing seems to work. Sometimes I get a PicoContainer Exception, sometimes (like for the above code) the object of type InsightReader is null after invoking ComponentAccessor.getOSGiComponentInstanceOfType. I probably messed up with Spring/OSGi annotations. Could you please suggest how to make it work?

Thank you

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events