Hi all,
I’ve been worrying about this problem all day. For a custom report, I need to access the historical information about sprints: which issues have been finished, which had been added and which issues had not been finished.
After some research, I found out, that HistoricSprintDataFactory exactly provides the information I need. Jira Software uses this factory for generating all the sprint reports.
As I need the information inside of Java, I try to inject HistoricSprintDataFactory, with not much success. It would be an alternative to use the REST interface, as the Atlassian reports do, but would prefer a Java-only solution.
So far I tried all the possibilities I am aware of. If I try to use the ComponentAccessor, it returns null:
@Autowired
public SprintProgressReport(JiraAuthenticationContext authContext) {
super();
this.sprintDataFactory = ComponentAccessor.getOSGiComponentInstanceOfType(HistoricSprintDataFactory.class);;
this.authContext = authContext;
}
As my plugin uses Spring Scanner v2, I also tried to inject it as ClasspathComponent:
@ClasspathComponent
private final HistoricSprintDataFactory sprintDataFactory;
@ComponentImport
private final JiraAuthenticationContext authContext;
@Autowired
public SprintProgressReport(JiraAuthenticationContext authContext, HistoricSprintDataFactory sprintDataFactory) {
super();
this.sprintDataFactory = sprintDataFactory;
this.authContext = authContext;
}
This results in the following error message, when activating the plugin:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'historicSprintDataFactory': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.atlassian.greenhopper.service.rapid.view.statistics.EstimateStatisticService com.atlassian.greenhopper.web.rapid.chart.HistoricSprintDataFactory.estimateStatisticService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.atlassian.greenhopper.service.rapid.view.statistics.EstimateStatisticService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
Here are my dependencies for Jira Software and the Spring Scanner configuration from the POM:
<dependency>
<groupId>com.atlassian.jira.plugins</groupId>
<artifactId>jira-greenhopper-plugin</artifactId>
<version>7.1.19</version>
<scope>provided</scope>
</dependency>
<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>
<applications>
<application>
<applicationKey>jira-software</applicationKey>
<version>${jira.version}</version>
</application>
</applications>
<enableQuickReload>true</enableQuickReload>
<enableFastdev>false</enableFastdev>
<instructions>
<Atlassian-Plugin-Key>${atlassian.plugin.key}</Atlassian-Plugin-Key>
<Export-Package/>
<Import-Package>org.springframework.osgi.*;resolution:="optional", org.eclipse.gemini.blueprint.*;resolution:="optional", com.atlassian.greenhopper.*;resolution:="optional", *</Import-Package>
<Spring-Context>*</Spring-Context>
</instructions>
</configuration>
</plugin>
I almost wanted to give up, but then saw it must be possible to access the factory, as ScriptRunner has it as an example in their documentation for implementing listeners:
import com.atlassian.greenhopper.service.rapid.view.RapidViewService
import com.atlassian.greenhopper.service.sprint.Sprint
import com.atlassian.greenhopper.web.rapid.chart.HistoricSprintDataFactory
import com.atlassian.jira.component.ComponentAccessor
import com.onresolve.scriptrunner.runner.customisers.PluginModuleCompilationCustomiser
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
@WithPlugin("com.pyxis.greenhopper.jira")
def historicSprintDataFactory = PluginModuleCompilationCustomiser.getGreenHopperBean(HistoricSprintDataFactory)
def rapidViewService = PluginModuleCompilationCustomiser.getGreenHopperBean(RapidViewService)
def user = ComponentAccessor.jiraAuthenticationContext.getLoggedInUser()
def sprint = event.sprint as Sprint
if (sprint.state == Sprint.State.CLOSED) {
def view = rapidViewService.getRapidView(user, sprint.rapidViewId).value
def sprintContents = historicSprintDataFactory.getSprintOriginalContents(user, view, sprint)
def sprintData = sprintContents.value
if (sprintData) {
def incompleteIssues = sprintData.contents.issuesNotCompletedInCurrentSprint*.issueId
log.warn "incompelte issues id : ${incompleteIssues}"
}
}
Anyone with an idea what I could try else, to make it work, especially the Spring Scanner specialists like @danielwester?
One additional observation: I am not so familiar with spring, but for me, it looks like HistoricSprintDataFactory is a plain Spring bean. Does that help?
Cheers,
Alexander