Why is it named "Spring" rather than "Headache Winter"? [Real case included]

Hi,

I'm injecting a ThirdPartyPluginLicenseStorageManager reference in an object construtor.

Then I get the exception below:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'thirdPartyPluginLicenseStorageManager' defined in URL [bundle://160.0:0/META-INF/spring/atlassian-plugins-components.xml]: Unsatisfied dependency expressed through constructor argument with index 2 of type [com.atlassian.sal.usercompatibility.UserManager]: : No unique bean of type [com.atlassian.sal.usercompatibility.UserManager] is defined: Unsatisfied dependency of type [interface com.atlassian.sal.usercompatibility.UserManager]: expected at least 1 matching bean; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.atlassian.sal.usercompatibility.UserManager] is defined: Unsatisfied dependency of type [interface com.atlassian.sal.usercompatibility.UserManager]: expected at least 1 matching bean
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:591)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:193)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:925)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:835)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:440)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
	at java.security.AccessController.doPrivileged(Native Method)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:728)
	at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.access$1600(AbstractDelegatedExecutionApplicationContext.java:69)
	at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext$4.run(AbstractDelegatedExecutionApplicationContext.java:355)
	at org.springframework.osgi.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85)
	at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.completeRefresh(AbstractDelegatedExecutionApplicationContext.java:320)
	at org.springframework.osgi.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor$CompleteRefreshTask.run(DependencyWaiterApplicationContextExecutor.java:132)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:662)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.atlassian.sal.usercompatibility.UserManager] is defined: Unsatisfied dependency of type [interface com.atlassian.sal.usercompatibility.UserManager]: expected at least 1 matching bean
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:613)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:622)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:584)
	... 22 more

Briefly:

The error

Error creating bean with name 'thirdPartyPluginLicenseStorageManager'

is because

No unique bean of type [com.atlassian.sal.usercompatibility.UserManager] is defined: Unsatisfied dependency of type [interface com.atlassian.sal.usercompatibility.UserManager]: expected at least 1 matching bean

The thirdPartyPluginLicenseStorageManager is defined in my atlassian-plugin.xml (it has atomatically added by the Atlassian Plugin SDK):

<component key="thirdPartyPluginLicenseStorageManager" class="com.atlassian.upm.license.storage.lib.ThirdPartyPluginLicenseStorageManagerImpl"/>

I've read the Atlassian documentation:

https://developer.atlassian.com/display/DOCS/Converting+from+Version+1+to+Version+2+%28OSGi%29+Plugins#ConvertingfromVersion1toVersion2%28OSGi%29Plugins-3.1SpecifyqualifiersonambiguousSpringdependencies

It suggest to use the @Qualifier annotation to help to Spring to resolve the ambiguity:

I've see that the Atlassian Plugin SDK has also added a reference to the UserManager in my atlassian-plugin.xml file:

<component-import key="userManager" interface="com.atlassian.sal.api.user.UserManager"/>

So I guess that:

@Qualifier("userManager")

should be added to the 3rd paramenter (userManager) in the ThirdPartyPluginLicenseStorageManagerImpl constructor:

public ThirdPartyPluginLicenseStorageManagerImpl(ApplicationProperties applicationProperties,

                                                     PluginAccessor pluginAccessor,

                                                     UserManager userManager)

    {

        this(applicationProperties, pluginAccessor, userManager, null);

    }

But, such code is not mine. It's provided by Atlassian in the plugin-license-storage-lib-2.13.3.jar file.

So, how can I resolve the it whether it looks like I need to add a qualifier to a code developed by Atlassian? Or is Spring so flexible to configure it in some way?.

Proposal: Spring name implies a brilliant, warm, happy thing. So, I guess it should be renamed to something more accurate like Advanced Shit.

Thanks,

Pablo

2 answers

1 accepted

1 vote
Ben Woskow Atlassian Team Oct 01, 2013

Hi Pablo,

Starting with v2.10.1, the Plugin License Storage library added support for username renaming, which is a new feature in JIRA 6.0 and Confluence 5.3. The API changed slightly to add this support, although it looks like the code generation tool hasn't been updated. (Alternatively, you may be on an older version of the SDK - let me know what version you're currently running).

I've filed https://ecosystem.atlassian.net/browse/PLUG-1045 to fix the codegen tool. In the meantime you can take the following steps to resolve your issue:

  1. Bump to the latest Plugin License Storage version (currently 2.13.3).
  2. Add a maven dependency for com.atlassian.usercompatibility:usercompatibility-sal (latest version is 0.5)
  3. Add a Spring component for com.atlassian.sal.usercompatibility.impl.CompatibilityUserManager

More details can be found here: https://bitbucket.org/atlassian/user-compatibility-sal

Cheers,
Ben

P.S. Thanks for the good laugh about the framework rename :)

Hi Ben,

This resolved the problem! The SDK version is the latest available: 4.2.9

Thank you very much!!

Pablo.

Ben,

Pablo never mentioned the JIRA version he was building for - should we use the version information on this page (Reference: https://ecosystem.atlassian.net/wiki/display/UPM/UPM+Bundling+Matrix) for the version of JIRA we're building for or just use the latest one?

I ask b/c I'm tracking down a SAL CompatibilityUserManager dependency problem and (among other things) switching my UPM License version back to 2.10.1 fixed it. Of course, just now I switched it back to 2.13.3 and it also worked, so something else 'fixed' the issue.

Does using 2.13.3 limit the generated plugin from working with versions of JIRA earlier than 6.1.1?

-wc

Ben Woskow Atlassian Team Dec 01, 2013

Using 2.13.3 of the licensing api doesn't restrict you from being compatible with older JIRA versions. If your add-on doesn't work in older versions then something else is likely causing problems.

Suggest an answer

Log in or Sign up to answer
How to earn badges on the Atlassian Community

How to earn badges on the Atlassian Community

Badges are a great way to show off community activity, whether you’re a newbie or a Champion.

Learn more
Community showcase
Published Jul 10, 2018 in Marketplace Apps

If you’re an Atlassian app developer, you’ll want to know about Atlas Camp!

This September 6-7, hundreds of Atlassian App developers will flock to Barcelona Spain to build skills, discover product roadmaps, meet face-to-face with the Atlassian team, and learn how to extend t...

179 views 0 4
Read article

Atlassian User Groups

Connect with like-minded Atlassian users at free events near you!

Find a group

Connect with like-minded Atlassian users at free events near you!

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you