Hi,
I’m looking for help resolving dependencies setting up a new plugin. We’re just starting out with Jira and need to add the ability to add an activity code to work log records. The available plugins add more complexity than we need.
My immediate goal is to intercept the CreateWorklog action and display my own version of the JSP page adding the required field and with my own action class sub-classing the CreateWorklog action class.
I’m getting the following when I invoke Log Work on an issue:
[INFO] [talledLocalContainer] org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.shipconstructor.jira.SsiCreateWorklog': Unsatisfied dependency expressed through constructor argument with index 3 of type [com.atlassian.jira.util.JiraDurationUtils]
I found two articles that are close, but didn’t help me.
- https://answers.atlassian.com/questions/59422/plugin-dependency-unresolved-constraint
The way I have it set up currently I have the following in pom.xml
<dependency> <groupId>com.atlassian.jira</groupId> <artifactId>jira-api</artifactId> <version>${jira.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.atlassian.jira</groupId> <artifactId>jira-core</artifactId> <version>${jira.version}</version> <scope>provided</scope> </dependency> ... <instructions> <Import-Package> ... com.atlassian.jira*;version="${jira.version}", ... </Import-Package> <Export-Package> com.shipconstructor.jira*;version="1.0", </Export-Package> </instructions> ...
I have included the jira-core just to try, but from what I can see in the Jira source, the failing dependency JiraDurationUtils, seems to be in the actual jira api.
The atlassian-plugin.xml file includes the following webwork1 module.
<webwork1 key="ssi-create-worklog" name="SSI Create Worklog"> <actions> <action name="com.shipconstructor.jira.SsiCreateWorklog" alias="CreateWorklog"> <view name="error">/secure/custom/com/shipconstructor/jira/worktypes/webwork/ssi-logwork.jsp</view> <view name="input">/secure/custom/com/shipconstructor/jira/worktypes/webwork/ssi-logwork.jsp</view> </action> </actions> </webwork1>
Taking care to match the alias CreateWorkLog with that used by Jira so as to override the action.
SsiCreateWorklog.java is very basic:
package com.shipconstructor.jira; import com.atlassian.jira.web.action.issue.CreateWorklog; import com.atlassian.jira.util.JiraDurationUtils; ... public class SsiCreateWorklog extends CreateWorklog { public SsiCreateWorklog(WorklogService worklogService, CommentService commentService, ProjectRoleManager projectRoleManager, JiraDurationUtils jiraDurationUtils, OutlookDateManager outlookDateManager, FieldVisibilityManager fieldVisibilityManager, final FieldLayoutManager fieldLayoutManager, final RendererManager rendererManager, UserUtil userUtil, final FeatureManager featureManager) { super(worklogService, commentService, projectRoleManager, jiraDurationUtils, outlookDateManager, fieldVisibilityManager, fieldLayoutManager, rendererManager, userUtil, featureManager); } }
The fourth constructor parameter is the one causing the trouble.
It doesn't get this far, but for completeness the JSP page is trivial page looks like:
<html> <body> <h1>Hello world</h1> </body> </html>
And this works fine if I navigate directly to it.
Jira starts up fine with this setup and the plugin shows enabled on the system page. However, when I go to an issue and invoke the Log Work action, it results in the following:
[INFO] [talledLocalContainer] 2013-06-07 14:42:08,416 http-2990-2 ERROR admin 882x1696x1 6oio4q 10.0.1.23 /secure/CreateWorklog!default.jspa [jira.config.webwork.JiraActionFactory] Error autowiring Action 'com.shipconstructor.jira.SsiCreateWorklog'.
[INFO] [talledLocalContainer] org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.shipconstructor.jira.SsiCreateWorklog': Unsatisfied dependency expressed through constructor argument with index 3 of type [com.atlassian.jira.util.JiraDurationUtils]: : No unique bean of type [com.atlassian.jira.util.JiraDurationUtils] is defined: Unsatisfied dependency of type [class com.atlassian.jira.util.JiraDurationUtils]: expected at least 1 matching bean; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.atlassian.jira.util.JiraDurationUtils] is defined: Unsatisfied dependency of type [class com.atlassian.jira.util.JiraDurationUtils]: expected at least 1 matching bean
[INFO] [talledLocalContainer] at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:591)
[INFO] [talledLocalContainer] at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:193)
I also tried adding the following to the atlassian-plugin.xml file
<component-import key="jiraDurationUtils" interface="com.atlassian.jira.util.JiraDurationUtils" />
but get the following on startup and the plugin was disabled:
[INFO] [talledLocalContainer] 2013-06-07 13:36:10,011 main ERROR [plugin.osgi.factory.OsgiPlugin] Never resolved service '&jiraDurationUtils' for
plugin 'com.shipconstructor.jira.worktypes' with filter (objectClass=com.atlassian.jira.util.JiraDurationUtils)
Any suggestions would be greatly appreciated. I've been going in circles on this one.
Community moderators have prevented the ability to post new answers.
Ah, the dreaded JiraDurationUtils, try use the snippet below instead of component-import in your atlassian-plugin.xml
<component key="jiraDurationUtils" name="JIRA Duration Utils" class="com.atlassian.jira.util.JiraDurationUtils"></component>
Thanks Patrick! This did work.
Can you offer any insight as to what this is doing? The plugin XML reference doesn't cover these tags and looking at the source this appears to be part of the api.
Thanks again...
Blair
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Blair,
<component-import> is introduced with Plugin 2 framework, works if the said component is exposed/marked as public. For the most part, it allows one plugin to expose its components and make them available to use by another plugin.
Now, JiraDurationUtils for some reason is not declared as public, so you cannot import it this way. But since it is available in the JIRA system, you can declare it as a component bean in your own plugin (as if the class is part of your plugin).
There is another way to get JiraDurationUtils, via code through ComponentManager, another handy way to get components that are otherwise not accessible, but looks like this is getting deprecated in JIRA 6.
ComponentManager.getInstance().getJiraDurationUtils();
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Patrick, thanks for that explanation. It does explain why I got stuck on that type and not others.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thank you so much guys, I had a similar problem but with ComponentLocator and ComponentFactory, and I was stuck for two days with that, but reading a lot and with your help, I could solve that: I had to add this to my atlassian-plugin.xml file:
<component key="componentLocator" name="Component Locator" class="com.atlassian.jira.util.JiraComponentLocator"> <interface>com.atlassian.jira.util.ComponentLocator</interface> </component> <component key="componentFactory" name="Component Factory" class="com.atlassian.jira.util.JiraComponentFactory"> <interface>com.atlassian.jira.util.ComponentFactory</interface> </component>
And that solved the problem !!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Jhonnatan, where is this "atlassian-plugin.xml" file located ?
I am trying to add the following component and stil its unable to find it..
The one that i can see is on the following path :
Hook_Plugin_Project >src >test >resource >atlassian-plugin.xml
and
Hook_Plugin_Project >src >main >resource >atlassian-plugin.xml
We tried adding <component-import key="authenticationContext" interface="com.atlassian.stash.user.StashAuthenticationContext"/> .. but that is not helping ..
Below are the logs
2015-11-25 11:10:21,627 ERROR [spring-startup] c.a.p.manager.DefaultPluginManager There was an error loading the descriptor 'My Pre Receive Repository Hook' of plugin 'com.att.icecream.icecream-plugin'. Disabling.
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.att.icecream.hook.MyPreReceiveRepositoryHook': Unsatisfied dependency expressed through constructor argument with index 0 of type [com.atlassian.stash.user.StashAuthenticationContext]: : No unique bean of type [com.atlassian.stash.user.StashAuthenticationContext] is defined: Unsatisfied dependency of type [interface com.atlassian.stash.user.StashAuthenticationContext]: expected at least 1 matching bean; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.atlassian.stash.user.StashAuthenticationContext] is defined: Unsatisfied dependency of type [interface com.atlassian.stash.user.StashAuthenticationContext]: expected at least 1 matching bean
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:591) ~[ConstructorResolver.class:4.1.6.RELEASE]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_05]
at com.atlassian.plugin.module.ClassPrefixModuleFactory.createModule(ClassPrefixModuleFactory.java:32) ~[ClassPrefixModuleFactory.class:na]
at com.atlassian.plugin.module.PrefixDelegatingModuleFactory.createModule(PrefixDelegatingModuleFactory.java:100) ~[PrefixDelegatingModuleFactory.class:na]
at com.atlassian.plugin.module.PrefixDelegatingModuleFactory$$FastClassBySpringCGLIB$$e05be356.invoke(<generated>) ~[ReflectUtils.class:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[MethodProxy.class:4.1.6.RELEASE]
at com.atlassian.stash.internal.plugin.OsgiSafeProxyProvider$1.invoke(OsgiSafeProxyProvider.java:93) ~[OsgiSafeProxyProvider$1.class:na]
at com.atlassian.plugin.module.PrefixDelegatingModuleFactory$$EnhancerBySpringCGLIB$$4f92a811.createModule(<generated>) ~[ReflectUtils.class:na]
at com.atlassian.stash.internal.plugin.RepositoryHookModuleDescriptor.enabled(RepositoryHookModuleDescriptor.java:145) ~[RepositoryHookModuleDescriptor.class:na]
at com.atlassian.plugin.manager.DefaultPluginManager.notifyModuleEnabled(DefaultPluginManager.java:2114) [DefaultPluginManager.class:na]
at com.atlassian.plugin.manager.DefaultPluginManager.enableConfiguredPluginModule(DefaultPluginManager.java:1888) [DefaultPluginManager.class:na]
at com.atlassian.plugin.manager.DefaultPluginManager.enableConfiguredPluginModules(DefaultPluginManager.java:1858) [DefaultPluginManager.class:na]
at com.atlassian.plugin.manager.DefaultPluginManager.addPlugins(DefaultPluginManager.java:1250) [DefaultPluginManager.class:na]
at com.atlassian.stash.internal.plugin.StashPluginManager.addPlugins(StashPluginManager.java:66) [StashPluginManager.class:na]
at com.atlassian.plugin.manager.DefaultPluginManager.earlyStartup(DefaultPluginManager.java:523) [DefaultPluginManager.class:na]
at com.atlassian.stash.internal.plugin.StashPluginManager.earlyStartup(StashPluginManager.java:46) [StashPluginManager.class:na]
at com.atlassian.plugin.manager.DefaultPluginManager.init(DefaultPluginManager.java:436) [DefaultPluginManager.class:na]
at com.atlassian.stash.internal.plugin.SpringPluginSystemLifecycle.start(SpringPluginSystemLifecycle.java:34) [SpringPluginSystemLifecycle.class:na]
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:173) [DefaultLifecycleProcessor.class:4.1.6.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:51) [DefaultLifecycleProcessor.class:4.1.6.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:346) [DefaultLifecycleProcessor$LifecycleGroup.class:4.1.6.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:149) [DefaultLifecycleProcessor.class:4.1.6.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:112) [DefaultLifecycleProcessor.class:4.1.6.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:770) [AbstractApplicationContext.class:4.1.6.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:483) [AbstractApplicationContext.class:4.1.6.RELEASE]
at javax.servlet.GenericServlet.init(GenericServlet.java:158) [servlet-api.jar:3.1.FR]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_05]
... 23 frames trimmed
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.atlassian.stash.user.StashAuthenticationContext] is defined: Unsatisfied dependency of type [interface com.atlassian.stash.user.StashAuthenticationContext]: expected at least 1 matching bean
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:613) ~[DefaultListableBeanFactory.class:4.1.6.RELEASE]
... 27 common frames omitted
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Blair,
<component-import> is introduced with Plugin 2 framework, works if the said component is exposed/marked as public. For the most part, it allows one plugin to expose its components and make them available to use by another plugin.
Now, JiraDurationUtils for some reason is not declared as public, so you cannot import it this way. But since it is available in the JIRA system, you can declare it as a component bean in your own plugin (as if the class is part of your plugin).
There is another way to get JiraDurationUtils, via code through ComponentManager, another handy way to get components that are otherwise not accessible, but looks like this is getting deprecated in JIRA 6.
ComponentManager.getInstance().getJiraDurationUtils();
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Community moderators have prevented the ability to post new answers.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.