Jira 11.x Plugin Migration – Unable to Inject services

Hello everyone,

We are currently migrating our legacy Data Center plugin to Jira 11.x, adapting it to: Jakarta (jakarta.*), Updated Spring versions, Removal of legacy javax.*, modern plugin framework changes ..

However, we are stuck on a dependency injection issue when accessing (for example) one of our servlets.
When accessing our servlet (used for initial addon configuration), Jira throws:

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'com.sykorait.vmcon.ConnectorSettingsServlet': 
Unsatisfied dependency expressed through constructor parameter 0: 

No qualifying bean of type 'com.atlassian.sal.api.user.UserManager' available: 
expected at least 1 bean which qualifies as autowire candidate.

No matter what combinations we try, we are not able to import and inject these components (UserManager, ApplicationProperties, ..)

In previous Jira versions (javax-based, older Spring), this worked correctly using: @ComponentImport, @Inject, @Scanned ..

We also tried what seems to be the now recommended JavaConfig-based OSGi approach using:

pom.xlm

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.sykorait.jira.plugins</groupId>
    <artifactId>USU-Service-Management-Connector</artifactId>
    <version>2.2.3</version>
    <organization>
        <name>Sykora IT s.r.o.</name>
        <url>https://www.sykorait.com</url>
    </organization>
    <name>USU Service Management Connector for Jira</name>
    <description>Integration between USU Service Management (Valuemation) and Jira.</description>
    <packaging>atlassian-plugin</packaging>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.glassfish.jaxb</groupId>
                <artifactId>jaxb-core</artifactId>
                <version>2.3.0.1</version>
            </dependency>

            <dependency>
                <groupId>org.glassfish.jaxb</groupId>
                <artifactId>jaxb-runtime</artifactId>
                <version>4.0.2</version>  
            </dependency>
     
            <dependency>
                <groupId>com.sun.istack</groupId>
                <artifactId>istack-commons-runtime</artifactId>
                <version>4.0.0</version>
            </dependency>

            <dependency>
                <groupId>com.sun.xml.fastinfoset</groupId>
                <artifactId>FastInfoset</artifactId>
                <version>1.2.17</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <!-- Jira 11.x changes-->
<dependency>
            <groupId>com.atlassian.plugins</groupId>
            <artifactId>atlassian-plugins-osgi-javaconfig</artifactId>
            <version>${osgi.javaconfig.version}</version>
        </dependency>
        <dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>2.1.1</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>com.sun.activation</groupId>
    <artifactId>jakarta.activation</artifactId>
    <version>1.2.2</version>
    <scope>provided</scope>
</dependency>

        <dependency>
    <groupId>commons-httpclient</groupId>
    <artifactId>commons-httpclient</artifactId>
    <version>3.1</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>jakarta.activation</groupId>
    <artifactId>jakarta.activation-api</artifactId>
    <version>2.1.1</version>
    <scope>provided</scope>
</dependency>

        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>2.10.10-atlassian-2</version> 
            <scope>provided</scope>               
        </dependency>
       
        <dependency>
            <groupId>jakarta.xml.bind</groupId>
            <artifactId>jakarta.xml.bind-api</artifactId>
            <version>4.0.0</version>
            <scope>provided</scope>
        </dependency>

        
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>4.0.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <version>6.0.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>jakarta.ws.rs</groupId>
            <artifactId>jakarta.ws.rs-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>jakarta.inject</groupId>
            <artifactId>jakarta.inject-api</artifactId>
            <version>2.0.1</version>
            <scope>provided</scope>
        </dependency>
        
        <dependency>
            <groupId>com.atlassian.applinks</groupId>
            <artifactId>applinks-api</artifactId>
            <version>8.0.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.atlassian.renderer</groupId>
            <artifactId>atlassian-renderer</artifactId>
            <version>8.0.5</version>
            <scope>provided</scope>
            <exclusions>
        
    </exclusions>
        </dependency>

        <dependency>
            <groupId>com.atlassian.templaterenderer</groupId>
            <artifactId>atlassian-template-renderer-api</artifactId>
            <version>5.0.2</version>
            <scope>provided</scope>
            <exclusions>
       
    </exclusions>
        </dependency>
        
        <dependency>
            <groupId>com.google.collections</groupId>
            <artifactId>google-collections</artifactId>
            <version>1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.atlassian.activeobjects</groupId>
            <artifactId>activeobjects-plugin</artifactId>
            <version>${ao.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.atlassian.upm</groupId>
            <artifactId>licensing-api</artifactId>
            <version>5.1.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.atlassian.upm</groupId>
            <artifactId>upm-api</artifactId>
            <version>5.1.2</version>
            <scope>provided</scope>
        </dependency>
		
		
        <dependency>
            <groupId>com.atlassian.jira</groupId>
            <artifactId>jira-api</artifactId>
            <version>${jira.version}</version>
            <scope>provided</scope>
			<exclusions>
                
                <exclusion>
                    <groupId>jta</groupId>
                    <artifactId>jta</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.atlassian.jira</groupId>
            <artifactId>jira-core</artifactId>
            <version>${jira.version}</version>
            <scope>provided</scope>
			<exclusions>
			  <exclusion>
				 <groupId>jndi</groupId>
				 <artifactId>jndi</artifactId>
			  </exclusion>
              <exclusion>
            <groupId>org.opensaml</groupId>
            <artifactId>opensaml-saml-api</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.opensaml</groupId>
            <artifactId>opensaml-saml-impl</artifactId>
        </exclusion>
            <exclusion>
                <groupId>jta</groupId>
                <artifactId>jta</artifactId>
            </exclusion>
			</exclusions>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.atlassian.plugin</groupId>
            <artifactId>atlassian-spring-scanner-annotation</artifactId>
            <version>${atlassian.spring.scanner.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.atlassian.plugin</groupId>
            <artifactId>atlassian-spring-scanner-runtime</artifactId>
            <version>${atlassian.spring.scanner.version}</version>
            <scope>runtime</scope>
        </dependency>
        
        <dependency>
            <groupId>com.atlassian.plugins</groupId>
            <artifactId>atlassian-plugins-osgi-testrunner</artifactId>
            <version>${plugin.testrunner.version}</version>
            <scope>test</scope>
        </dependency>
		
       
        <dependency>
			<groupId>com.atlassian.plugins.rest</groupId>
			<artifactId>atlassian-rest-v2-api</artifactId>
			<version>8.0.6</version>
			<scope>provided</scope>
		</dependency>
        <dependency>
            <groupId>com.atlassian.sal</groupId>
            <artifactId>sal-api</artifactId>
            <version>7.2.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.wink</groupId>
            <artifactId>wink-client</artifactId>
            <version>1.4</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <version>1.8.5</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.1.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.6.6</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.atlassian.upm</groupId>
            <artifactId>plugin-license-storage-lib</artifactId>
            <version>${upm.license.compatibility.version}</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.atlassian.upm</groupId>
            <artifactId>plugin-license-storage-plugin</artifactId>
            <version>${upm.license.compatibility.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
            <scope>compile</scope>
        </dependency>
       <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <repositories>
        <repository>
            <id>central</id>
            <url>https://repo.maven.apache.org/maven2/</url>
        </repository>
        <repository>
            <id>atlassian-public</id>
            <url>https://packages.atlassian.com/maven-public/</url>
            </repository>
    </repositories>
    <pluginRepositories>
    <pluginRepository>
        <id>atlassian-public</id>
        <url>https://packages.atlassian.com/maven-public/</url>
    </pluginRepository>
    </pluginRepositories>
    <build>
        <plugins>
            <plugin>
                <groupId>com.atlassian.maven.plugins</groupId>
                <artifactId>jira-maven-plugin</artifactId>
                <version>${amps.version}</version>
                <extensions>true</extensions>
                <configuration>
                    <!--<applications>
                        <application>
                            <applicationKey>jira-servicedesk</applicationKey>
                            <version>${jira.servicedesk.application.version}</version>
                        </application>
                    </applications>-->
                    <productVersion>${jira.version}</productVersion>
                    <productDataVersion>${jira.version}</productDataVersion>
                    <!-- Uncomment to install TestKit backdoor in JIRA. -->
                    <!--
                    <pluginArtifacts>
                        <pluginArtifact>
                            <groupId>com.atlassian.jira.tests</groupId>
                            <artifactId>jira-testkit-plugin</artifactId>
                            <version>${testkit.version}</version>
                        </pluginArtifact>
                    </pluginArtifacts>
                    -->
                    <enableQuickReload>true</enableQuickReload>
                    <!-- See here for an explanation of default instructions: -->
                    <!-- https://developer.atlassian.com/docs/advanced-topics/configuration-of-instructions-in-atlassian-plugins -->
                    <instructions>
                        <Atlassian-Plugin-Key>${atlassian.plugin.key}</Atlassian-Plugin-Key>
                        <!-- Add package to export here -->
                        <Export-Package>com.sykorait.jira.plugins.vmconnector.api,</Export-Package>
                        <!-- Add package import here -->
                        <Import-Package>
                            !javax.*,
                            jakarta.servlet*;version="[6.0.0,7.0.0)",
                            jakarta.ws.rs*;version="[3.0.0,4.0.0)",
                            jakarta.inject*;version="[2.0.0,3.0.0)",
                            jakarta.annotation*;version="[2.0.0,3.0.0)",
                            jakarta.xml.bind*;version="[4.0.0,5.0.0)",
                            com.atlassian.jira.plugin.webfragment.conditions,
                            org.springframework.osgi.*;resolution:="optional",
                            org.eclipse.gemini.blueprint.*;resolution:="optional",
                            com.atlassian.upm.*;resolution:="optional",
                            *
                        </Import-Package>
                        <!-- Ensure plugin is spring powered -->
                        <Spring-Context>*</Spring-Context>
                        <Private-Package>com.atlassian.upm.license.storage.lib*</Private-Package>
                        <!-- <DynamicImport-Package>com.atlassian.upm.api.license.entity;version="2.0.1", com.atlassian.upm.api.license;version="2.0.1", com.atlassian.upm.api.util;version="2.0.1", com.atlassian.upm.license.storage.plugin;version="${upm.license.compatibility.version}"</DynamicImport-Package>-->
                    </instructions>
                    <bundledArtifacts>
                        <bundledArtifact>
                            <groupId>com.atlassian.upm</groupId>
                            <artifactId>atlassian-universal-plugin-manager-plugin</artifactId>
                            <version>5.1.2</version>
                        </bundledArtifact>
                        <bundledArtifact>
                            <groupId>com.atlassian.upm</groupId>
                            <artifactId>plugin-license-storage-plugin</artifactId>
                            <version>${upm.license.compatibility.version}</version>
                        </bundledArtifact>
                    </bundledArtifacts>
                </configuration>
            </plugin>
            <plugin>
                <groupId>com.atlassian.plugin</groupId>
                <artifactId>atlassian-spring-scanner-maven-plugin</artifactId>
                <version>${atlassian.spring.scanner.version}</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>atlassian-spring-scanner</goal>
                        </goals>
                        <phase>process-classes</phase>
                    </execution>
                </executions>
                <configuration>
                    <includeExclude>-com.atlassian.plugin.spring.scanner.annotation.*</includeExclude>
                    <scannedDependencies>
                        <dependency>
                            <groupId>com.atlassian.plugin</groupId>
                            <artifactId>atlassian-spring-scanner-external-jar</artifactId>
                        </dependency>
                    </scannedDependencies>
                    <verbose>false</verbose>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-storage-plugin</id>
                        <phase>process-resources</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${project.build.outputDirectory}</outputDirectory>
                            <includeArtifactIds>plugin-license-storage-plugin</includeArtifactIds>
                            <stripVersion>true</stripVersion>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <!--
            <plugin>
                <groupId>org.owasp</groupId>
                <artifactId>dependency-check-maven</artifactId>
                <version>7.0.4</version>
                <configuration>
                    <skipProvidedScope>true</skipProvidedScope>
                    <suppressionFiles>
                        <suppressionFile>https://dcapt-downloads.s3.amazonaws.com/atlassian-security-scanner-dc-apps-suppressions.xml</suppressionFile>
                    </suppressionFiles>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>check</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            -->

        </plugins>
    </build>
    <properties>
        <ao.version>6.1.2</ao.version>
       <jira.version>11.3.0</jira.version>
        <amps.version>9.9.1</amps.version>
        <osgi.javaconfig.version>0.6.0</osgi.javaconfig.version>
        <atlassian.spring.scanner.version>3.0.3</atlassian.spring.scanner.version>  <!-- proven stable -->
        <spring.version>5.3.39-atlassian-3</spring.version>
        <jira.servicedesk.application.version>4.15.0 </jira.servicedesk.application.version>
        <plugin.testrunner.version>2.0.1</plugin.testrunner.version>
        <!-- This property ensures consistency between the key in atlassian-plugin.xml and the OSGi bundle's key. -->
        <atlassian.plugin.key>${project.groupId}.${project.artifactId}</atlassian.plugin.key>
        <!-- TestKit version 6.x for JIRA 6.x -->
        <testkit.version>6.3.11</testkit.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!-- Jira 11.x changes-->
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <maven.compiler.release>21</maven.compiler.release>
        <upm.license.compatibility.version>2.15.3</upm.license.compatibility.version>
    </properties>
</project>

servlet:

package com.sykorait.vmcon;

import com.atlassian.activeobjects.external.ActiveObjects;
import com.atlassian.jira.util.json.JSONException;
import com.atlassian.jira.util.json.JSONObject;
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
import com.atlassian.sal.api.ApplicationProperties;
import com.atlassian.sal.api.auth.LoginUriProvider;
import com.atlassian.sal.api.user.UserManager;
import com.atlassian.templaterenderer.TemplateRenderer;
import com.atlassian.upm.api.license.PluginLicenseManager;
import com.atlassian.upm.api.license.entity.PluginLicense;

import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;

@Named
public class ConnectorSettingsServlet extends HttpServlet {

    private static final String TEMPLATE = "templates/connector-settings.vm";

  
    private final PluginLicenseManager pluginLicenseManager;
    private final TemplateRenderer templateRenderer;
    private final UserManager userManager;
    private final LoginUriProvider loginUriProvider;
    private final ActiveObjects ao;
    private final ApplicationProperties applicationProperties;

    public ConnectorSettingsServlet(UserManager userManager, ApplicationProperties applicationProperties, LoginUriProvider loginUriProvider, PluginLicenseManager pluginLicenseManager, TemplateRenderer templateRenderer, ActiveObjects ao) {
        this.pluginLicenseManager = pluginLicenseManager;
        this.templateRenderer = templateRenderer;
        this.userManager = userManager;
        this.loginUriProvider = loginUriProvider;
        this.applicationProperties = applicationProperties;
        this.ao = ao;
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        Map<String, Object> context = new HashMap<>();
        context.put("baseUrl", applicationProperties.getBaseUrl());
        res.setContentType("text/html;charset=utf-8");

        if (pluginLicenseManager.getLicense().isDefined()) {
          .....
        }
    }

    private void redirectToLogin(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.sendRedirect(loginUriProvider.getLoginUri(getUri(request)).toASCIIString());
    }

    private URI getUri(HttpServletRequest request) {
        StringBuffer builder = request.getRequestURL();
        if (request.getQueryString() != null) {
            builder.append("?").append(request.getQueryString());
        }
        return URI.create(builder.toString());
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        ... 
    }
}

JavaConfig (following the attlassian myPlugin tutorial)

package com.sykorait.vmcon;

import com.atlassian.activeobjects.external.ActiveObjects;
import com.atlassian.sal.api.ApplicationProperties;
import com.atlassian.sal.api.auth.LoginUriProvider;
import com.atlassian.sal.api.user.UserManager;
import com.atlassian.templaterenderer.TemplateRenderer;
import com.atlassian.upm.api.license.PluginLicenseManager;
import com.atlassian.plugins.osgi.javaconfig.ExportOptions;
import com.atlassian.plugins.osgi.javaconfig.configs.beans.ModuleFactoryBean;
import com.atlassian.plugins.osgi.javaconfig.configs.beans.PluginAccessorBean;
import org.osgi.framework.ServiceRegistration;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import jakarta.servlet.http.HttpServlet;

import static com.atlassian.plugins.osgi.javaconfig.OsgiServices.exportOsgiService;
import static com.atlassian.plugins.osgi.javaconfig.OsgiServices.importOsgiService;

@Configuration
@Import({ModuleFactoryBean.class, PluginAccessorBean.class})
public class SpringConfig {

    // Import OSGi services
    @Bean
    public ApplicationProperties applicationProperties() {
        return importOsgiService(ApplicationProperties.class);
    }

    @Bean
    public UserManager userManager() {
        return importOsgiService(UserManager.class);
    }

    @Bean
    public LoginUriProvider loginUriProvider() {
        return importOsgiService(LoginUriProvider.class);
    }

    @Bean
    public PluginLicenseManager pluginLicenseManager() {
        return importOsgiService(PluginLicenseManager.class);
    }

    @Bean
    public TemplateRenderer templateRenderer() {
        return importOsgiService(TemplateRenderer.class);
    }

    @Bean
    public ActiveObjects activeObjects() {
        return importOsgiService(ActiveObjects.class);
    }

    // Create servlet using the OSGi services
    @Bean
    public ConnectorSettingsServlet connectorSettingsServlet(
            UserManager userManager,
            ApplicationProperties applicationProperties,
            LoginUriProvider loginUriProvider,
            PluginLicenseManager pluginLicenseManager,
            TemplateRenderer templateRenderer,
            ActiveObjects activeObjects) {

        return new ConnectorSettingsServlet(
                userManager,
                applicationProperties,
                loginUriProvider,
                pluginLicenseManager,
                templateRenderer,
                activeObjects
        );
    }

    // Optional: Export servlet as OSGi service (if needed)
    @Bean
    public FactoryBean<ServiceRegistration> registerConnectorServlet(ConnectorSettingsServlet servlet) {
        return exportOsgiService(servlet, ExportOptions.as(ConnectorSettingsServlet.class));
    }
}

Is there something fundamentally different about how services must be imported or exposed in Jira 11?

@MartinFischer Could you try setting a debug point inside the UserManager @Bean method and see if it’s executed? Also if you’re at Atlas Camp @MarekTokarski and I are at the Product & Design booth this week

Thanks for the suggestion @mkemp I tried to add logging inside the UserManager @Bean method but nothing appears in the Jira logs. I also cannot debug it directly because there isn’t a compatible Atlassian SDK for Jira 11 if I am not mistaken. So it seems the bean method is never actually called during plugin load. I am not really sure what we are missing here.

I believe something similar was already discussed here.

Edit:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:atlassian-scanner="http://www.atlassian.com/schema/atlassian-scanner/2"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.atlassian.com/schema/atlassian-scanner/2
        http://www.atlassian.com/schema/atlassian-scanner/2/atlassian-scanner.xsd">
    <atlassian-scanner:scan-indexes/>
</beans>

This and @Named, @Inject annotations probably have solved this problem.

@MartinFischer are you sure you got the correct Spring version? Jira 11 upgraded to version 6.2.x RFC-77: Upgrades to Spring and Jakarta versions. We made no change to Spring annotations, and usermanager still imports with @ComponentImport for our services. Not that I think it should actually matter for a provided dependency, but perhaps this in combination with your import-package statements in MANIFEST.mf, this can explain the behavior? Incidentally, what does import-package look like in your bundled manifest?

@MartinFischer From the Spring XML it looks like two parts are missing to use OSGi Java Config

  1. The Java config file is not declared as a bean
  2. Annotation scanning is not enabled (<atlassian-scanner:scan-indexes/> is only for Atlassian Spring Scanner, it is not for Spring)

It should be like:

    <context:annotation-config/>
    <bean class="com.sykorait.vmcon.SpringConfig "/>

See an example in our open source platform: https://bitbucket.org/atlassian/dc-platform/src/b8448ee818c277c6b1eb7fec661abdbe4d0d8490/refapp/refapp-plugins/ao-plugin/src/main/resources/META-INF/spring/spring.xml#lines-8,9