Hi,
I am trying to build an Bitbucket post commit hook plugin but I cannot build. What should I do?
This is the stack trace:
[INFO] [talledLocalContainer] 2015-12-02 09:51:39,020 WARN [ThreadPoolAsyncTaskExecutor::Thread 54] admin @IMM5LKx591x423x0 127.0.0.1 "POST /rest/plugins/1.0/ HTTP/1.1" c.a.plugin.osgi.factory.OsgiPlugin Ignoring the bean container that was just created for plugin t.e.a.b.post-commit. The plugin is in an invalid state, DISABLED, that doesn't support a transition to enabled. Most likely, it was disabled due to a timeout. [INFO] [talledLocalContainer] 2015-12-02 09:51:40,044 ERROR [UpmAsynchronousTaskManager:thread-1] admin @IMM5LKx591x423x0 127.0.0.1 "POST /rest/plugins/1.0/ HTTP/1.1" c.a.p.m.PrefixDelegatingModuleFactory Detected an error instantiating the module via Spring. This usually means that you haven't created a <component-import> for the interface you're trying to use. https://developer.atlassian.com/x/TAEr for more details. [INFO] [talledLocalContainer] 2015-12-02 09:51:40,052 ERROR [UpmAsynchronousTaskManager:thread-1] admin @IMM5LKx591x423x0 127.0.0.1 "POST /rest/plugins/1.0/ HTTP/1.1" c.a.p.manager.DefaultPluginManager There was an error loading the descriptor 'Post Commit Hook' of plugin 't.e.a.b.post-commit'. Disabling. [INFO] [talledLocalContainer] org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 't.e.a.b.hook.PostCommitHook': Unsatisfied dependency expressed through constructor argument with index 0 of type [t.e.a.b.services.CustomEmailServiceImpl]: : No qualifying bean of type [t.e.a.b.services.CustomEmailServiceImpl] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [t.e.a.b.services.CustomEmailServiceImpl] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {} [INFO] [talledLocalContainer] at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) ~[ConstructorResolver.class:4.1.7.RELEASE] [INFO] [talledLocalContainer] at com.atlassian.plugin.module.ClassPrefixModuleFactory.createModule(ClassPrefixModuleFactory.java:39) ~[ClassPrefixModuleFactory.class:na] [INFO] [talledLocalContainer] at com.atlassian.plugin.module.PrefixDelegatingModuleFactory.createModule(PrefixDelegatingModuleFactory.java:100) ~[PrefixDelegatingModuleFactory.class:na] [INFO] [talledLocalContainer] at com.atlassian.plugin.module.PrefixDelegatingModuleFactory$$FastClassBySpringCGLIB$$e05be356.invoke(<generated>) ~[ReflectUtils.class:na] [INFO] [talledLocalContainer] at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[MethodProxy.class:4.1.7.RELEASE] [INFO] [talledLocalContainer] at com.atlassian.stash.internal.plugin.OsgiSafeProxyProvider$1.invoke(OsgiSafeProxyProvider.java:93) ~[OsgiSafeProxyProvider$1.class:na] [INFO] [talledLocalContainer] at com.atlassian.plugin.module.PrefixDelegatingModuleFactory$$EnhancerBySpringCGLIB$$6ce0023e.createModule(<generated>) ~[ReflectUtils.class:na] [INFO] [talledLocalContainer] at com.atlassian.stash.internal.plugin.RepositoryHookModuleDescriptor.enabled(RepositoryHookModuleDescriptor.java:145) ~[RepositoryHookModuleDescriptor.class:na] [INFO] [talledLocalContainer] at com.atlassian.plugin.manager.DefaultPluginManager.notifyModuleEnabled(DefaultPluginManager.java:2168) [DefaultPluginManager.class:na] [INFO] [talledLocalContainer] at com.atlassian.plugin.manager.DefaultPluginManager.enableConfiguredPluginModule(DefaultPluginManager.java:1850) [DefaultPluginManager.class:na] [INFO] [talledLocalContainer] at com.atlassian.plugin.manager.DefaultPluginManager.enableConfiguredPluginModules(DefaultPluginManager.java:1822) [DefaultPluginManager.class:na] [INFO] [talledLocalContainer] at com.atlassian.plugin.manager.DefaultPluginManager.enableDependentPlugins(DefaultPluginManager.java:1268) [DefaultPluginManager.class:na] [INFO] [talledLocalContainer] at com.atlassian.plugin.manager.DefaultPluginManager.addPlugins(DefaultPluginManager.java:1221) [DefaultPluginManager.class:na] [INFO] [talledLocalContainer] at com.atlassian.stash.internal.plugin.StashPluginManager.addPlugins(StashPluginManager.java:122) [StashPluginManager.class:na] [INFO] [talledLocalContainer] at com.atlassian.plugin.manager.DefaultPluginManager.scanForNewPlugins(DefaultPluginManager.java:884) [DefaultPluginManager.class:na] [INFO] [talledLocalContainer] at com.atlassian.plugin.manager.DefaultPluginManager.installPlugins(DefaultPluginManager.java:783) [DefaultPluginManager.class:na] [INFO] [talledLocalContainer] at com.atlassian.stash.internal.plugin.ClusteredPluginController.installPlugins(ClusteredPluginController.java:96) [ClusteredPluginController.class:na] [INFO] [talledLocalContainer] at com.atlassian.plugin.util.ContextClassLoaderSettingInvocationHandler.invoke(ContextClassLoaderSettingInvocationHandler.java:30) [ContextClassLoaderSettingInvocationHandler.class:na] [INFO] [talledLocalContainer] at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:56) [gemini-blueprint-core-2.0.0.BUILD-atlassian-m002.jar:2.0.0.BUILD-atlassian-m002] [INFO] [talledLocalContainer] at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:60) [gemini-blueprint-core-2.0.0.BUILD-atlassian-m002.jar:2.0.0.BUILD-atlassian-m002] [INFO] [talledLocalContainer] at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invokeUnprivileged(ServiceTCCLInterceptor.java:70) [gemini-blueprint-core-2.0.0.BUILD-atlassian-m002.jar:2.0.0.BUILD-atlassian-m002] [INFO] [talledLocalContainer] at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invoke(ServiceTCCLInterceptor.java:53) [gemini-blueprint-core-2.0.0.BUILD-atlassian-m002.jar:2.0.0.BUILD-atlassian-m002] [INFO] [talledLocalContainer] at org.eclipse.gemini.blueprint.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:57) [gemini-blueprint-core-2.0.0.BUILD-atlassian-m002.jar:2.0.0.BUILD-atlassian-m002] [INFO] [talledLocalContainer] at com.atlassian.upm.core.install.AbstractPluginInstallHandler$1.doInTransaction(AbstractPluginInstallHandler.java:143) [atlassian-universal-plugin-manager-plugin-2.20.1_1448829286000.jar:na] [INFO] [talledLocalContainer] at com.atlassian.upm.core.install.AbstractPluginInstallHandler$1.doInTransaction(AbstractPluginInstallHandler.java:138) [atlassian-universal-plugin-manager-plugin-2.20.1_1448829286000.jar:na] [INFO] [talledLocalContainer] at com.atlassian.sal.core.transaction.HostContextTransactionTemplate$1.doInTransaction(HostContextTransactionTemplate.java:21) [HostContextTransactionTemplate$1.class:na] [INFO] [talledLocalContainer] at com.atlassian.stash.internal.sal.spi.HostContextAccessorImpl.doInTransaction(HostContextAccessorImpl.java:54) [HostContextAccessorImpl.class:na] [INFO] [talledLocalContainer] at com.atlassian.plugin.util.ContextClassLoaderSettingInvocationHandler.invoke(ContextClassLoaderSettingInvocationHandler.java:30) [ContextClassLoaderSettingInvocationHandler.class:na] [INFO] [talledLocalContainer] at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:56) [gemini-blueprint-core-2.0.0.BUILD-atlassian-m002.jar:2.0.0.BUILD-atlassian-m002] [INFO] [talledLocalContainer] at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:60) [gemini-blueprint-core-2.0.0.BUILD-atlassian-m002.jar:2.0.0.BUILD-atlassian-m002] [INFO] [talledLocalContainer] at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invokeUnprivileged(ServiceTCCLInterceptor.java:70) [gemini-blueprint-core-2.0.0.BUILD-atlassian-m002.jar:2.0.0.BUILD-atlassian-m002] [INFO] [talledLocalContainer] at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invoke(ServiceTCCLInterceptor.java:53) [gemini-blueprint-core-2.0.0.BUILD-atlassian-m002.jar:2.0.0.BUILD-atlassian-m002] [INFO] [talledLocalContainer] at org.eclipse.gemini.blueprint.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:57) [gemini-blueprint-core-2.0.0.BUILD-atlassian-m002.jar:2.0.0.BUILD-atlassian-m002] [INFO] [talledLocalContainer] at com.atlassian.sal.core.transaction.HostContextTransactionTemplate.execute(HostContextTransactionTemplate.java:18) [HostContextTransactionTemplate.class:na] [INFO] [talledLocalContainer] at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:56) [gemini-blueprint-core-2.0.0.BUILD-atlassian-m002.jar:2.0.0.BUILD-atlassian-m002] [INFO] [talledLocalContainer] at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:60) [gemini-blueprint-core-2.0.0.BUILD-atlassian-m002.jar:2.0.0.BUILD-atlassian-m002] [INFO] [talledLocalContainer] at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invokeUnprivileged(ServiceTCCLInterceptor.java:70) [gemini-blueprint-core-2.0.0.BUILD-atlassian-m002.jar:2.0.0.BUILD-atlassian-m002] [INFO] [talledLocalContainer] at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invoke(ServiceTCCLInterceptor.java:53) [gemini-blueprint-core-2.0.0.BUILD-atlassian-m002.jar:2.0.0.BUILD-atlassian-m002] [INFO] [talledLocalContainer] at org.eclipse.gemini.blueprint.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:57) [gemini-blueprint-core-2.0.0.BUILD-atlassian-m002.jar:2.0.0.BUILD-atlassian-m002] [INFO] [talledLocalContainer] at com.atlassian.upm.core.install.AbstractPluginInstallHandler.installArtifacts(AbstractPluginInstallHandler.java:137) [atlassian-universal-plugin-manager-plugin-2.20.1_1448829286000.jar:na] [INFO] [talledLocalContainer] at com.atlassian.upm.core.install.AbstractPluginInstallHandler.installArtifact(AbstractPluginInstallHandler.java:123) [atlassian-universal-plugin-manager-plugin-2.20.1_1448829286000.jar:na] [INFO] [talledLocalContainer] at com.atlassian.upm.core.install.JarPluginInstallHandler.installPluginInternal(JarPluginInstallHandler.java:52) [atlassian-universal-plugin-manager-plugin-2.20.1_1448829286000.jar:na] [INFO] [talledLocalContainer] at com.atlassian.upm.core.install.AbstractPluginInstallHandler.installPlugin(AbstractPluginInstallHandler.java:64) [atlassian-universal-plugin-manager-plugin-2.20.1_1448829286000.jar:na] [INFO] [talledLocalContainer] at com.atlassian.upm.core.install.DefaultPluginInstallationService.execute(DefaultPluginInstallationService.java:117) [atlassian-universal-plugin-manager-plugin-2.20.1_1448829286000.jar:na] [INFO] [talledLocalContainer] at com.atlassian.upm.core.install.DefaultPluginInstallationService.install(DefaultPluginInstallationService.java:91) [atlassian-universal-plugin-manager-plugin-2.20.1_1448829286000.jar:na] [INFO] [talledLocalContainer] at com.atlassian.upm.install.UpmPluginInstallationService.install(UpmPluginInstallationService.java:97) [atlassian-universal-plugin-manager-plugin-2.20.1_1448829286000.jar:na] [INFO] [talledLocalContainer] at com.atlassian.upm.core.rest.resources.install.InstallTask.installFromFile(InstallTask.java:156) [atlassian-universal-plugin-manager-plugin-2.20.1_1448829286000.jar:na] [INFO] [talledLocalContainer] at com.atlassian.upm.core.rest.resources.install.InstallFromFileTask.executeTask(InstallFromFileTask.java:37) [atlassian-universal-plugin-manager-plugin-2.20.1_1448829286000.jar:na] [INFO] [talledLocalContainer] at com.atlassian.upm.core.rest.resources.install.InstallTask.run(InstallTask.java:81) [atlassian-universal-plugin-manager-plugin-2.20.1_1448829286000.jar:na] [INFO] [talledLocalContainer] at com.atlassian.upm.core.async.AsynchronousTaskManager.executeTask(AsynchronousTaskManager.java:124) [atlassian-universal-plugin-manager-plugin-2.20.1_1448829286000.jar:na] [INFO] [talledLocalContainer] at com.atlassian.upm.core.async.AsynchronousTaskManager$1.call(AsynchronousTaskManager.java:102) [atlassian-universal-plugin-manager-plugin-2.20.1_1448829286000.jar:na] [INFO] [talledLocalContainer] at com.atlassian.upm.core.async.AsynchronousTaskManager$1.call(AsynchronousTaskManager.java:99) [atlassian-universal-plugin-manager-plugin-2.20.1_1448829286000.jar:na] [INFO] [talledLocalContainer] at com.atlassian.sal.core.executor.ThreadLocalDelegateCallable.call(ThreadLocalDelegateCallable.java:38) [ThreadLocalDelegateCallable.class:na] [INFO] [talledLocalContainer] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_45] [INFO] [talledLocalContainer] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_45] [INFO] [talledLocalContainer] at java.lang.Thread.run(Thread.java:745) [na:1.8.0_45] [INFO] [talledLocalContainer] ... 83 frames trimmed [INFO] [talledLocalContainer] Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [t.e.a.b.services.CustomEmailServiceImpl] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {} [INFO] [talledLocalContainer] at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1301) ~[DefaultListableBeanFactory.class:4.1.7.RELEASE] [INFO] [talledLocalContainer] ... 56 common frames omitted
My custom service:
package t.e.a.b.services; import com.atlassian.bitbucket.permission.Permission; import com.atlassian.bitbucket.permission.PermissionAdminService; import com.atlassian.bitbucket.permission.PermittedGroup; import com.atlassian.bitbucket.permission.PermittedUser; import com.atlassian.bitbucket.repository.Repository; import com.atlassian.bitbucket.user.ApplicationUser; import com.atlassian.bitbucket.user.SecurityService; import com.atlassian.bitbucket.user.UserService; import com.atlassian.bitbucket.util.Page; import com.atlassian.bitbucket.util.PageRequest; import com.atlassian.bitbucket.util.PageUtils; import com.atlassian.plugin.spring.scanner.annotation.export.ExportAsService; import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport; import javax.inject.Inject; import javax.inject.Named; import java.util.EnumSet; import java.util.HashSet; import java.util.Set; @ExportAsService({CustomEmailService.class}) @Named("customEmailService") public class CustomEmailServiceImpl implements CustomEmailService { @ComponentImport private final PermissionAdminService permissionAdminService; @ComponentImport private final SecurityService securityService; @ComponentImport private final UserService userService; @Inject public CustomEmailServiceImpl( PermissionAdminService permissionAdminService, SecurityService securityService, UserService userService ) { this.permissionAdminService = permissionAdminService; this.securityService = securityService; this.userService = userService; } public Set<String> getEmails(final Repository repository) {...} public Set<String> getAllEmails() {...} private Set<String> getProjectPermittedMails(Repository repository, PageRequest pageRequest) {...} private Set<String> getAllMails(PageRequest pageRequest) {...} private Set<String> getRepositoryPermittedMails(Repository repository, PageRequest pageRequest) {...} private Set<String> getGroupMembersMails(PermittedGroup permittedGroup, PageRequest pageRequest) {...} }
AsyncPostReceiveRepositoryHook implementation:
package t.e.a.b.hook; import com.atlassian.bitbucket.hook.repository.AsyncPostReceiveRepositoryHook; import com.atlassian.bitbucket.hook.repository.RepositoryHookContext; import com.atlassian.bitbucket.repository.RefChange; import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport; import t.e.a.b.services.CustomEmailService; import t.e.a.b.services.CustomEmailServiceImpl; import javax.annotation.Nonnull; import javax.inject.Inject; import java.util.Collection; import java.util.Set; public class PostCommitHook implements AsyncPostReceiveRepositoryHook { @ComponentImport private final CustomEmailService customEmailService; @Inject public PostCommitHook(CustomEmailServiceImpl customEmailService) { this.customEmailService = customEmailService; } @Override public void postReceive(@Nonnull RepositoryHookContext context, @Nonnull Collection<RefChange> refChanges) { Set<String> emails = customEmailService.getAllEmails(); System.out.println(emails); } }
My atlassian-plugin.xml:
<?xml version="1.0" encoding="UTF-8"?> <atlassian-plugin key="${atlassian.plugin.key}" name="${project.name}" plugins-version="2"> <plugin-info> <description>${project.description}</description> <version>${project.version}</version> <vendor name="${project.organization.name}" url="${project.organization.url}"/> <param name="plugin-icon">images/pluginIcon.png</param> <param name="plugin-logo">images/pluginLogo.png</param> </plugin-info> <!-- add our i18n resource --> <resource type="i18n" name="i18n" location="post-commit"/> <!-- add our web resources --> <web-resource key="post-commit-resources" name="post-commit Web Resources"> <dependency>com.atlassian.auiplugin:ajs</dependency> <resource type="download" name="post-commit.css" location="/css/post-commit.css"/> <resource type="download" name="post-commit.js" location="/js/post-commit.js"/> <resource type="download" name="images/" location="/images"/> <context>post-commit</context> </web-resource> <repository-hook key="post-commit-hook" name="Post Commit Hook" i18n-name-key="post-commit-hook.name" class="t.e.a.b.hook.PostCommitHook"> <description key="post-commit-hook.description">The Post Commit Hook Plugin</description> <icon>icon-example.png</icon> <config-form name="Post Commit Hook Config" key="post-commit-hook-config"> <view>t.e.a.b.hook.postcommithook.view</view> <directory location="/static/"/> </config-form> </repository-hook> </atlassian-plugin>
I also tried to add <component-import> and <component> tags to atlassian-plugin.xml but it was not working, too.
Community moderators have prevented the ability to post new answers.
I added components with "atlas-create-bitbucket-plugin-module". Component configuration came with xml configuration. I changed to annotation based configuration. It's working now. The problem solved but I don't understand how.
Note: I didn't add @Component to my PostCommitHook class.
Hi,
You don't need the <component> and <component-import> tags anymore, as these were used before the Atlassian Spring Scanner wiring which is based on annotations.
I don't see your pom.xml, so please make sure that you have the necessary dependency declarations for the Atlassian Spring Scanner as documented here:
https://bitbucket.org/atlassian/atlassian-spring-scanner
Please also note that you only need ExportAsService when you want to expose that component as an OSGi service, which is not necessary if you only want to use this class internally in your plug-in.
Could you please try to add @Component in front of your PostCommitHook class declaration?
Hope this helps.
Cheers,
Michael
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
How do you access a class internally in your plugin? I've tried ComponentImport with Inject with no success. Results in start up errors in unable to resolve service.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Here's an example how it works.
@Component public class A implements InterfaceA { }
Then you can inject this into other classes:
@Scanned public class SomeClass { @ComponentImport private final InterfaceA a; @Autowired public SomeClass(InterfaceA a) { this.a = a; } }
Sometimes it's necessary to define your component in the META-INF/spring/plugin-context.xml.
<?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" 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 http://www.atlassian.com/schema/atlassian-scanner/atlassian-scanner.xsd"> <atlassian-scanner:scan-indexes/> <bean id="a" class="your.package.class.A" autowire="byName"/> </beans>
I've noticed, that there are three and sometimes only two possible imports (depending to the Springscanner version) for the @component annotation.
If you can import org.springframework.stereotype.Component you don't need the Bean definition in the plugin-context.xml. If you use org.osgi.service.component.annotations.Component you have to.
This works with Springscanner < 2. If you're using Springscanner > 2 omit the @scanned annotation and replace @autowired with @inject.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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.