Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

Atlassian Jira Plugin. Spring Scanner service injection fails (NoSuchBeanDefinitionException for cu

icygirl277
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
September 29, 2025

Hi everyone,

I’m developing a Jira Server/Data Center plugin and I’m stuck with Spring Scanner service injection. I keep getting NoSuchBeanDefinitionException although I think I have annotated everything correctly.

Environment

  • Jira: 10.3.9

  • active-objects: 6.1.2

  • atlassian-spring-scanner version: 3.0.4

Trace

org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'de.jiraplugin.Sure':
Unsatisfied dependency expressed through constructor parameter 0;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'de.jiraplugin.BookedHoursTransactions' available:
expected at least 1 bean which qualifies as autowire candidate.

Relevant Code

Service interface

import com.atlassian.activeobjects.external.ActiveObjects;
import com.atlassian.plugin.spring.scanner.annotation.component.Component;
import com.atlassian.plugin.spring.scanner.annotation.export.ExportAsService;
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;

import javax.inject.Inject;

@Component
@ExportAsService({BookedHoursTransactions.class})
public class BookedHoursTransactionsImpl implements BookedHoursTransactions {

private final ActiveObjects ao;

@Inject
public BookedHoursTransactionsImpl(@ComponentImport ActiveObjects ao) {
this.ao = ao;
}

@Override
public void doSomething() {
// ...
}
}

 Servlet

import javax.inject.Inject;

import javax.inject.Named;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import com.atlassian.jira.bc.issue.search.SearchService;

import com.atlassian.jira.component.ComponentAccessor;

import com.atlassian.jira.issue.CustomFieldManager;

import com.atlassian.jira.issue.link.IssueLinkManager;

import com.atlassian.jira.issue.worklog.WorklogManager;

import com.atlassian.jira.security.groups.GroupManager;

import com.atlassian.jira.user.ApplicationUser;

import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;

import com.atlassian.sal.api.auth.LoginUriProvider;

import com.atlassian.sal.api.user.UserManager;

import com.atlassian.templaterenderer.TemplateRenderer;

import com.atlassian.webresource.api.assembler.PageBuilderService;

import com.google.common.collect.Maps;

 

import de.jiraplugin.issues.DataGetter;

import de.jiraplugin.issues.Sponsor;

 

@Named

public class Sure extends HttpServlet {
...
 

private SearchService searchService;

private TemplateRenderer templateRenderer;

private final UserManager userManager;

private final CustomFieldManager customFieldManager;

private final WorklogManager worklogManager;

private final IssueLinkManager issueLinkManager;

private final GroupManager groupManager;

private final LoginUriProvider loginUriProvider;

private final PageBuilderService pageBuilderService;

 

private final BookedHoursTransactions bookedHoursTransactions;

 

@Inject

public Sure(BookedHoursTransactions bookedHoursTransactions) {

super();

this.searchService = ComponentAccessor.getComponent(SearchService.class);

this.templateRenderer = ComponentAccessor.getComponent(TemplateRenderer.class);

this.userManager = ComponentAccessor.getComponent(UserManager.class);

this.customFieldManager = ComponentAccessor.getComponent(CustomFieldManager.class);

this.worklogManager = ComponentAccessor.getComponent(WorklogManager.class);

this.issueLinkManager = ComponentAccessor.getComponent(IssueLinkManager.class);

this.groupManager = ComponentAccessor.getComponent(GroupManager.class);

this.loginUriProvider = ComponentAccessor.getComponent(LoginUriProvider.class);

this.pageBuilderService = ComponentAccessor.getComponent(PageBuilderService.class);

this.bookedHoursTransactions = bookedHoursTransactions;

}






2 answers

0 votes
Aron Gombas _Midori_
Community Champion
September 29, 2025

I noticed that there is no "package x.y.z" in the first line of your Java code. Are you sure that your beans are in the expected packages?

(If you copied fragments without those lines, then ignore this.)

icygirl277
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
September 29, 2025

I only copied a snippet, in my actual code the package declarations exist

0 votes
Jayesh Raghuvanshi
Contributor
September 29, 2025

 

Thanks for sharing the details — this is a classic Spring Scanner gotcha when building Jira Server/DC plugins. Let’s break it down and fix why you’re getting:

 

NoSuchBeanDefinitionException: No qualifying bean of type 'de.jiraplugin.BookedHoursTransactions'
 

 
🔍 What’s Going On
You annotated your service class correctly:

@Component @ExportAsService({BookedHoursTransactions.class}) public class BookedHoursTransactionsImpl implements BookedHoursTransactions { ... }
✅ That should make it a Spring-managed bean and export it as a service available for injection.

But your servlet (Sure) is just annotated with @Named, not with any Spring Scanner wiring.
This means Spring Scanner does not recognize Sure as a Spring component eligible for constructor injection.

✅ Fix Options
Option 1: Annotate Your Servlet as a Component
If you want Sure to be injected like any other bean:

 

import com.atlassian.plugin.spring.scanner.annotation.component.Scanned; @Scanned @Named public class Sure extends HttpServlet { private final BookedHoursTransactions bookedHoursTransactions; @Inject public Sure(BookedHoursTransactions bookedHoursTransactions) { this.bookedHoursTransactions = bookedHoursTransactions; } ... }
 

 
Here’s what changed:

Added @Scanned → tells Spring Scanner to process it.

Kept @Named → identifies it as a bean.

Now Spring can inject your BookedHoursTransactions.

Option 2: Use @ComponentImport Instead
If your servlet is not meant to be a Spring-managed component (common for servlets/resources declared in atlassian-plugin.xml), then don’t use constructor injection. Instead, use @ComponentImport on a field or constructor param:

 

@Named public class Sure extends HttpServlet { private final BookedHoursTransactions bookedHoursTransactions; @Inject public Sure(@ComponentImport BookedHoursTransactions bookedHoursTransactions) { this.bookedHoursTransactions = bookedHoursTransactions; } }
 

 
This works if BookedHoursTransactions is exported as a service (@ExportAsService on your Impl, which you already have).

Option 3: Fallback (Not Recommended)
If nothing else works, you can manually fetch it via the OSGi container:

 

BookedHoursTransactions service = ComponentAccessor.getOSGiComponentInstanceOfType(BookedHoursTransactions.class);
 

 
But that bypasses Spring Scanner’s purpose — keep this only for debugging.

📝 Checklist
Ensure atlassian-spring-scanner is set up correctly in your pom.xml:

<plugin> <groupId>com.atlassian.plugin</groupId> <artifactId>atlassian-spring-scanner-maven-plugin</artifactId> <version>3.0.4</version> <executions> <execution> <goals> <goal>atlassian-spring-scanner</goal> </goals> </execution> </executions> </plugin>
Run mvn clean install and make sure the generated-sources/annotations include your service in META-INF/spring.

Double-check your atlassian-plugin.xml — if you’re declaring Sure as a servlet there, you need @ComponentImport (Option 2).

👉 From your code, the most likely fix is to change your servlet’s constructor to:

 

@Inject public Sure(@ComponentImport BookedHoursTransactions bookedHoursTransactions) { this.bookedHoursTransactions = bookedHoursTransactions; }


 

icygirl277
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
September 29, 2025

Thanks, but I think @Scanned doesnt exist in version 3 anymore? And option 2 didnt work as well :( And does option 3 take the implemented version of BookedoursTransactions?

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
CLOUD
PRODUCT PLAN
FREE
TAGS
AUG Leaders

Atlassian Community Events