jira - How to use Active Objects with annotation in atlassian sdk -
i jira plugin , need use active object. (jira v7.1.8) in official documentation outdated. written using xml, if understood correctly, used atlassian spring scanner (i use v1.2.3)
following manual https://bitbucket.org/atlassian/atlassian-spring-scanner/src/1.2.x/readme.md?at=1.2.x&fileviewer=file-view-default nothing succeeded.
atlassian-plugin.xml
<atlassian-plugin key="${project.groupid}.${project.artifactid}" 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="dbplugin"/> <web-resource key="my-resources"> <dependency>com.atlassian.jira.jira-project-config-plugin:project-config-global</dependency> <context>my-resources</context> </web-resource> <!----------- old xml version ------------------ <component-import key="ao" name="active objects service" interface="com.atlassian.activeobjects.external.activeobjects"> <description>component access active objects functionality plugin</description> </component-import> <component key="dao-factory" class="com.lemon.dbplugin.dao.daofactory"> </component> --------------------------------------------------------> <ao key="ao-module"> <entity>com.lemon.dbplugin.entity.studententity</entity> </ao> <webwork1 key="actions" name="myactions"> <actions> <action name="com.lemon.dbplugin.actionalpha" alias="action" roles-required="admin"> <view name="success">/templates/success.vm</view> </action> </actions> </webwork1>
actionalpha
package com.lemon.dbplugin; import com.atlassian.jira.project.project; import com.atlassian.jira.web.action.jirawebactionsupport; import com.lemon.dbplugin.dao.daofactory; import com.lemon.dbplugin.entity.studententity; import com.lemon.dbplugin.logic.student; import com.lemon.dbplugin.logic.studentimpl; import org.apache.log4j.logger; import webwork.action.servletactioncontext; public class actionalpha extends jirawebactionsupport { private static final logger log = logger.getlogger(actionalpha.class); private project project; private studententity[] students; @override public string execute() throws exception { log.debug("entered in execute actionalpha"); project = getselectedprojectobject(); gethttprequest().setattribute("com.atlassian.jira.projectconfig.util.servletrequestprojectconfigrequestcache:project", project); students = daofactory.getinstance().getstudentdao().getstudents(); log.debug("students :" + students); return super.execute(); } public string doadd() throws exception { log.debug("entered in doadd actionalpha"); string name = gethttprequest().getparametervalues("name")[0]; student student = new studentimpl(name); log.debug("student :" + student); daofactory.getinstance().getstudentdao().addstudent(student); servletactioncontext.getresponse().sendredirect("/secure/action.jspa"); return none; }
}
daofactory
package com.lemon.dbplugin.dao; import com.atlassian.activeobjects.external.activeobjects; import com.atlassian.plugin.spring.scanner.annotation.imports.componentimport; import com.lemon.dbplugin.dao.impl.studentdaoimpl; import org.springframework.beans.factory.annotation.autowired; import org.springframework.stereotype.component; @component public class daofactory { private static studentdao studentdao = null; private static daofactory instance = null; @componentimport private static activeobjects ao; @autowired public daofactory(@componentimport activeobjects ao) { daofactory.ao = ao; } public static synchronized daofactory getinstance() { if (instance == null) { instance = new daofactory(ao); } return instance; } public studentdao getstudentdao() { if (studentdao == null) { studentdao = new studentdaoimpl(ao); } return studentdao; }
}
studentdaoimpl
package com.lemon.dbplugin.dao.impl; import com.atlassian.activeobjects.external.activeobjects; import com.atlassian.plugin.spring.scanner.annotation.imports.componentimport; import com.atlassian.sal.api.transaction.transactioncallback; import com.lemon.dbplugin.dao.studentdao; import com.lemon.dbplugin.entity.studententity; import com.lemon.dbplugin.logic.student; import org.apache.log4j.logger; import org.springframework.beans.factory.annotation.autowired; import java.util.date; public class studentdaoimpl implements studentdao { private final activeobjects ao; private static final logger log = logger.getlogger(studentdaoimpl.class); @autowired public studentdaoimpl(@componentimport activeobjects ao) { this.ao = ao; } @override public studententity addstudent(final student student) throws exception { log.debug("entered addstudents"); log.debug("ao :" + ao); return ao.executeintransaction(new transactioncallback<studententity>() { public studententity dointransaction() { studententity entity = ao.create(studententity.class); entity.setname(student.getname()); entity.setcreated(new date(system.currenttimemillis())); entity.save(); return entity; } }); } public studententity[] getstudents() throws exception { log.debug("entered getstudents"); log.debug("ao: " + ao); try { return ao.executeintransaction(new transactioncallback<studententity[]>() { public studententity[] dointransaction() { studententity[] result = ao.find(studententity.class); if (result != null) { return ao.find(studententity.class); } else { return new studententity[]{}; } } }); } catch(nullpointerexception e){ return new studententity[]{}; } } }
compile , package whithout errors. if try open /jira/secure/action.jspa, in console this:
[info] [talledlocalcontainer] 2016-06-30 09:38:15,837 http-nio-2990-exec-8 debug admin 578x129x1 bnt30i 10.0.0.120 /rest/plugins/1.0/com.lemon.dbplugin.dbplugin-key [c.a.activeobjects.osgi.osgiserviceutilsimpl] registering service net.java.ao.atlassian.atlassiantablenameconverter@16856656 interface net.java.ao.schema.tablenameconverter , properties {com.atlassian.plugin.key=com.lemon.dbplugin.dbplugin} [info] [talledlocalcontainer] 2016-06-30 09:38:15,839 http-nio-2990-exec-8 debug admin 578x129x1 bnt30i 10.0.0.120 /rest/plugins/1.0/com.lemon.dbplugin.dbplugin-key [c.a.activeobjects.osgi.osgiserviceutilsimpl] registering service com.atlassian.activeobjects.config.internal.defaultactiveobjectsconfiguration@3cf99a08 interface com.atlassian.activeobjects.config.activeobjectsconfiguration , properties {com.atlassian.plugin.key=com.lemon.dbplugin.dbplugin} [info] [talledlocalcontainer] 2016-06-30 09:38:15,845 http-nio-2990-exec-8 debug admin 578x129x1 bnt30i 10.0.0.120 /rest/plugins/1.0/com.lemon.dbplugin.dbplugin-key [c.a.activeobjects.osgi.activeobjectsservicefactory] onpluginmoduleenabledevent storing unattached <ao> configuration module [com.lemon.dbplugin.dbplugin] [info] [talledlocalcontainer] 2016-06-30 09:38:15,875 http-nio-2990-exec-8 debug admin 578x129x1 bnt30i 10.0.0.120 /rest/plugins/1.0/com.lemon.dbplugin.dbplugin-key [c.a.activeobjects.osgi.activeobjectsservicefactory] onpluginenabledevent attaching unbound <ao> [com.lemon.dbplugin.dbplugin] [info] [talledlocalcontainer] 2016-06-30 09:38:15,876 http-nio-2990-exec-8 debug admin 578x129x1 bnt30i 10.0.0.120 /rest/plugins/1.0/com.lemon.dbplugin.dbplugin-key [c.a.activeobjects.osgi.tenantawareactiveobjects] init bundle [com.lemon.dbplugin.dbplugin] [info] [talledlocalcontainer] 2016-06-30 09:38:15,876 http-nio-2990-exec-8 debug admin 578x129x1 bnt30i 10.0.0.120 /rest/plugins/1.0/com.lemon.dbplugin.dbplugin-key [c.a.activeobjects.osgi.tenantawareactiveobjects] bundle [com.lemon.dbplugin.dbplugin] loading new ao promise jiratenantimpl{id='system'} [info] [talledlocalcontainer] 2016-06-30 09:38:15,876 http-nio-2990-exec-8 debug admin 578x129x1 bnt30i 10.0.0.120 /rest/plugins/1.0/com.lemon.dbplugin.dbplugin-key [c.a.activeobjects.osgi.tenantawareactiveobjects] setaoconfiguration [com.lemon.dbplugin.dbplugin] [info] [talledlocalcontainer] 2016-06-30 09:38:15,876 http-nio-2990-exec-8 debug admin 578x129x1 bnt30i 10.0.0.120 /rest/plugins/1.0/com.lemon.dbplugin.dbplugin-key [c.a.activeobjects.osgi.tenantawareactiveobjects] bundle [com.lemon.dbplugin.dbplugin] got activeobjectsconfiguration [info] [talledlocalcontainer] 2016-06-30 09:38:15,877 active-objects-init-jiratenantimpl{id='system'}-0 debug admin [c.a.activeobjects.osgi.tenantawareactiveobjects] bundle [com.lemon.dbplugin.dbplugin] creating activeobjects [info] [talledlocalcontainer] 2016-06-30 09:38:15,905 active-objects-init-jiratenantimpl{id='system'}-0 debug admin [c.a.activeobjects.osgi.tenantawareactiveobjects] bundle [com.lemon.dbplugin.dbplugin] created activeobjects [info] [talledlocalcontainer] 2016-06-30 09:38:53,798 http-nio-2990-exec-12 error admin 578x184x1 bnt30i 10.0.0.120 /secure/action.jspa [c.a.j.config.webwork.jiraactionfactory] error autowiring action 'com.lemon.dbplugin.actionalpha'. [info] [talledlocalcontainer] java.lang.nullpointerexception [info] [talledlocalcontainer] @ com.atlassian.jira.config.webwork.jiraactionfactory$jirapluginactionfactory.getactionimpl(jiraactionfactory.java:389) [info] [talledlocalcontainer] @ webwork.action.factory.prefixactionfactoryproxy.getactionimpl(prefixactionfactoryproxy.java:99) [info] [talledlocalcontainer] @ webwork.action.factory.jspactionfactoryproxy.getactionimpl(jspactionfactoryproxy.java:59) [info] [talledlocalcontainer] @ webwork.action.factory.commandactionfactoryproxy.getactionimpl(commandactionfactoryproxy.java:60) [info] [talledlocalcontainer] @ com.atlassian.jira.config.webwork.lookupaliasactionfactoryproxy.getactionimpl(lookupaliasactionfactoryproxy.java:61) [info] [talledlocalcontainer] @ webwork.action.factory.commandactionfactoryproxy.getactionimpl(commandactionfactoryproxy.java:60) [info] [talledlocalcontainer] @ webwork.action.factory.contextactionfactoryproxy.getactionimpl(contextactionfactoryproxy.java:36) [info] [talledlocalcontainer] @ webwork.action.factory.prepareactionfactoryproxy.getactionimpl(prepareactionfactoryproxy.java:37) [info] [talledlocalcontainer] @ com.atlassian.jira.config.webwork.jiraactionfactory$safeparametersettingactionfactoryproxy.getactionimpl(jiraactionfactory.java:147) [info] [talledlocalcontainer] @ webwork.action.factory.chainingactionfactoryproxy.getactionimpl(chainingactionfactoryproxy.java:53) [info] [talledlocalcontainer] @ com.atlassian.jira.config.webwork.jiraactionfactory.getactionimpl(jiraactionfactory.java:301) [info] [talledlocalcontainer] ... 2 filtered [info] [talledlocalcontainer] @ javax.servlet.http.httpservlet.service(httpservlet.java:725) [info] [talledlocalcontainer] ... 55 filtered [info] [talledlocalcontainer] @ com.atlassian.greenhopper.jira.filters.classicboardrouter.dofilter(classicboardrouter.java:59) [info] [talledlocalcontainer] ... 27 filtered [info] [talledlocalcontainer] @ com.atlassian.labs.httpservice.resource.resourcefilter.dofilter(resourcefilter.java:59) [info] [talledlocalcontainer] ... 38 filtered [info] [talledlocalcontainer] @ com.atlassian.jira.security.jirasecurityfilter.dofilter(jirasecurityfilter.java:70) [info] [talledlocalcontainer] ... 38 filtered [info] [talledlocalcontainer] @ com.atlassian.servicedesk.internal.web.customercontextsettingfilter.lambda$invokefilterchain$0(customercontextsettingfilter.java:169) [info] [talledlocalcontainer] @ com.atlassian.servicedesk.internal.util.scala.scalajavainterop$1.apply(scalajavainterop.java:25) [info] [talledlocalcontainer] @ com.atlassian.servicedesk.internal.utils.context.customercontextutil$.outofcustomercontext(customercontextutil.scala:48) [info] [talledlocalcontainer] @ com.atlassian.servicedesk.internal.utils.context.customercontextutil.outofcustomercontext(customercontextutil.scala) [info] [talledlocalcontainer] @ com.atlassian.servicedesk.internal.utils.context.customercontextserviceimpl.outofcustomercontext(customercontextserviceimpl.java:24) [info] [talledlocalcontainer] @ com.atlassian.servicedesk.internal.web.customercontextsettingfilter.outofcustomercontext(customercontextsettingfilter.java:164) [info] [talledlocalcontainer] @ com.atlassian.servicedesk.internal.web.customercontextsettingfilter.dofilterimpl(customercontextsettingfilter.java:120) [info] [talledlocalcontainer] @ com.atlassian.servicedesk.internal.web.customercontextsettingfilter.dofilter(customercontextsettingfilter.java:112) [info] [talledlocalcontainer] ... 55 filtered [info] [talledlocalcontainer] @ java.util.concurrent.threadpoolexecutor.runworker(threadpoolexecutor.java:1142) [info] [talledlocalcontainer] @ java.util.concurrent.threadpoolexecutor$worker.run(threadpoolexecutor.java:617) [info] [talledlocalcontainer] @ org.apache.tomcat.util.threads.taskthread$wrappingrunnable.run(taskthread.java:61) [info] [talledlocalcontainer] @ java.lang.thread.run(thread.java:745) [info] [talledlocalcontainer] 2016-06-30 09:38:53,801 http-nio-2990-exec-12 error admin 578x184x1 bnt30i 10.0.0.120 /secure/action.jspa [c.a.j.web.dispatcher.jirawebworkactiondispatcher] exception thrown action 'action', returning 404 [info] [talledlocalcontainer] java.lang.nullpointerexception [info] [talledlocalcontainer] @ com.atlassian.jira.config.webwork.jiraactionfactory$jirapluginactionfactory.getactionimpl(jiraactionfactory.java:389) [info] [talledlocalcontainer] @ webwork.action.factory.prefixactionfactoryproxy.getactionimpl(prefixactionfactoryproxy.java:99) [info] [talledlocalcontainer] @ webwork.action.factory.jspactionfactoryproxy.getactionimpl(jspactionfactoryproxy.java:59) [info] [talledlocalcontainer] @ webwork.action.factory.commandactionfactoryproxy.getactionimpl(commandactionfactoryproxy.java:60) [info] [talledlocalcontainer] @ com.atlassian.jira.config.webwork.lookupaliasactionfactoryproxy.getactionimpl(lookupaliasactionfactoryproxy.java:61) [info] [talledlocalcontainer] @ webwork.action.factory.commandactionfactoryproxy.getactionimpl(commandactionfactoryproxy.java:60) [info] [talledlocalcontainer] @ webwork.action.factory.contextactionfactoryproxy.getactionimpl(contextactionfactoryproxy.java:36) [info] [talledlocalcontainer] @ webwork.action.factory.prepareactionfactoryproxy.getactionimpl(prepareactionfactoryproxy.java:37) [info] [talledlocalcontainer] @ com.atlassian.jira.config.webwork.jiraactionfactory$safeparametersettingactionfactoryproxy.getactionimpl(jiraactionfactory.java:147) [info] [talledlocalcontainer] @ webwork.action.factory.chainingactionfactoryproxy.getactionimpl(chainingactionfactoryproxy.java:53) [info] [talledlocalcontainer] @ com.atlassian.jira.config.webwork.jiraactionfactory.getactionimpl(jiraactionfactory.java:301) [info] [talledlocalcontainer] ... 2 filtered [info] [talledlocalcontainer] @ javax.servlet.http.httpservlet.service(httpservlet.java:725) [info] [talledlocalcontainer] ... 55 filtered [info] [talledlocalcontainer] @ com.atlassian.greenhopper.jira.filters.classicboardrouter.dofilter(classicboardrouter.java:59) [info] [talledlocalcontainer] ... 27 filtered [info] [talledlocalcontainer] @ com.atlassian.labs.httpservice.resource.resourcefilter.dofilter(resourcefilter.java:59) [info] [talledlocalcontainer] ... 38 filtered [info] [talledlocalcontainer] @ com.atlassian.jira.security.jirasecurityfilter.dofilter(jirasecurityfilter.java:70) [info] [talledlocalcontainer] ... 38 filtered [info] [talledlocalcontainer] @ com.atlassian.servicedesk.internal.web.customercontextsettingfilter.lambda$invokefilterchain$0(customercontextsettingfilter.java:169) [info] [talledlocalcontainer] @ com.atlassian.servicedesk.internal.util.scala.scalajavainterop$1.apply(scalajavainterop.java:25) [info] [talledlocalcontainer] @ com.atlassian.servicedesk.internal.utils.context.customercontextutil$.outofcustomercontext(customercontextutil.scala:48) [info] [talledlocalcontainer] @ com.atlassian.servicedesk.internal.utils.context.customercontextutil.outofcustomercontext(customercontextutil.scala) [info] [talledlocalcontainer] @ com.atlassian.servicedesk.internal.utils.context.customercontextserviceimpl.outofcustomercontext(customercontextserviceimpl.java:24) [info] [talledlocalcontainer] @ com.atlassian.servicedesk.internal.web.customercontextsettingfilter.outofcustomercontext(customercontextsettingfilter.java:164) [info] [talledlocalcontainer] @ com.atlassian.servicedesk.internal.web.customercontextsettingfilter.dofilterimpl(customercontextsettingfilter.java:120) [info] [talledlocalcontainer] @ com.atlassian.servicedesk.internal.web.customercontextsettingfilter.dofilter(customercontextsettingfilter.java:112) [info] [talledlocalcontainer] ... 55 filtered [info] [talledlocalcontainer] @ java.util.concurrent.threadpoolexecutor.runworker(threadpoolexecutor.java:1142) [info] [talledlocalcontainer] @ java.util.concurrent.threadpoolexecutor$worker.run(threadpoolexecutor.java:617) [info] [talledlocalcontainer] @ org.apache.tomcat.util.threads.taskthread$wrappingrunnable.run(taskthread.java:61) [info] [talledlocalcontainer] @ java.lang.thread.run(thread.java:745)
sorry stupid question, doing wrong?
after weeks of searching web , lot's of trial error, got official active objects tutorial work latest version of jira (7.1.2) , spring-scanner 2.0 support.
you can find full code sample on github, here gist of it:
declare depenencies correctly
<!-- active objects --> <dependency> <groupid>com.atlassian.activeobjects</groupid> <artifactid>activeobjects-plugin</artifactid> <version>${ao.version}</version> <scope>provided</scope> </dependency> <!-- sal, active objects plugin uses sal's api transactions --> <dependency> <groupid>com.atlassian.sal</groupid> <artifactid>sal-api</artifactid> <version>${sal.version}</version> <scope>provided</scope> </dependency> <!-- dependency injection --> <dependency> <groupid>org.springframework</groupid> <artifactid>spring-context</artifactid> <version>${spring.version}</version> <scope>provided</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>org.slf4j</groupid> <artifactid>slf4j-simple</artifactid> <version>${slf4j.version}</version> <scope>compile</scope> </dependency>
configure spring scanner
<build> <plugins> <plugin> <groupid>com.atlassian.maven.plugins</groupid> <artifactid>maven-jira-plugin</artifactid> <version>${amps.version}</version> <extensions>true</extensions> <configuration> <productversion>${jira.version}</productversion> <productdataversion>${jira.version}</productdataversion> <enablequickreload>true</enablequickreload> <enablefastdev>false</enablefastdev> <instructions> <atlassian-plugin-key>${atlassian.plugin.key}</atlassian-plugin-key> <!-- add package export here --> <export-package>com.atlassian.tutorial.ao.todo.api,</export-package> <!-- add package import here --> <import-package> org.springframework.osgi.*;resolution:="optional", org.eclipse.gemini.blueprint.*;resolution:="optional", * </import-package> <!-- ensure plugin spring powered --> <spring-context>*</spring-context> </instructions> </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> <verbose>false</verbose> </configuration> </plugin> </plugins> </build>
properties
<properties> <!-- key used keep consistency between key in atlassian-plugin.xml , key generate bundle. --> <atlassian.plugin.key>${project.groupid}.${project.artifactid}</atlassian.plugin.key> <jira.version>7.2.1</jira.version> <!-- correct versions use atlassian product see target folder, i.e. /target/container/tomcat8x/cargo-jira-home/webapps/jira/web-inf/lib --> <amps.version>6.2.4</amps.version> <ao.version>1.0.0</ao.version> <sal.version>2.6.0</sal.version> <slf4j.version>1.7.9</slf4j.version> <testkit.version>6.3.11</testkit.version> <plugin.testrunner.version>1.2.3</plugin.testrunner.version> <spring.version>4.1.6.release</spring.version> <!-- see https://bitbucket.org/atlassian/atlassian-spring-scanner --> <atlassian.spring.scanner.version>1.2.6</atlassian.spring.scanner.version> <!--determined jee compliant container--> <servlet.version>3.1.0</servlet.version> </properties>
** spring context** need configure spring /resources/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/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 autowire="constructor" /> </beans>
java beans
then can use @component
mark java class dependency injection.
since put autowire="constructor"
in our plugin-context.xml
, don't need @autowired
or @inject
annotations constructor injection anymore.
your own beans injected automatically, external beans have market @componentimport
:
@component public final class todoservlet extends httpservlet { private final todoservice todoservice; private final usermanager usermanager; public todoservlet(todoservice todoservice, @componentimport usermanager usermanager) { this.todoservice = todoservice; this.usermanager = usermanager; }
hence, can import active objects follows:
public todoserviceimpl(@componentimport activeobjects ao) { this.ao = ao; }
make sure not ao
in constructor, since not ready jet!
hope helps
Comments
Post a Comment