Skip to content

Commit fef37e6

Browse files
authored
fix api changes for jira 9 version (#11)
1 parent ca6aeef commit fef37e6

File tree

3 files changed

+78
-48
lines changed

3 files changed

+78
-48
lines changed

Diff for: build.gradle

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ allprojects {
2424
version '1.0-SNAPSHOT'
2525

2626
sourceCompatibility = 1.8
27+
targetCompatibility = 1.8
2728

2829
apply plugin: 'java'
2930
apply plugin: 'groovy'
@@ -50,4 +51,4 @@ licenseReport {
5051
configurations = ['compile']
5152
excludeOwnGroup = true
5253
renderers = [new InventoryHtmlReportRenderer('InventoryHtmlReportRenderer.html', 'Dependency licenses')]
53-
}
54+
}

Diff for: integrations/jira/src/main/java/com/devexperts/switchboard/integrations/jira/JiraIntegrationFeatures.java

+74-45
Original file line numberDiff line numberDiff line change
@@ -9,33 +9,28 @@
99

1010
import com.atlassian.httpclient.apache.httpcomponents.DefaultHttpClientFactory;
1111
import com.atlassian.httpclient.api.HttpClient;
12+
import com.atlassian.httpclient.api.Response;
1213
import com.atlassian.httpclient.api.factory.HttpClientOptions;
1314
import com.atlassian.jira.rest.client.api.AuthenticationHandler;
14-
import com.atlassian.jira.rest.client.api.GetCreateIssueMetadataOptionsBuilder;
1515
import com.atlassian.jira.rest.client.api.JiraRestClient;
16-
import com.atlassian.jira.rest.client.api.domain.BasicComponent;
17-
import com.atlassian.jira.rest.client.api.domain.BasicIssue;
18-
import com.atlassian.jira.rest.client.api.domain.CimIssueType;
19-
import com.atlassian.jira.rest.client.api.domain.CimProject;
20-
import com.atlassian.jira.rest.client.api.domain.Issue;
21-
import com.atlassian.jira.rest.client.api.domain.IssueType;
22-
import com.atlassian.jira.rest.client.api.domain.Project;
23-
import com.atlassian.jira.rest.client.api.domain.User;
16+
import com.atlassian.jira.rest.client.api.domain.*;
2417
import com.atlassian.jira.rest.client.auth.BasicHttpAuthenticationHandler;
2518
import com.atlassian.jira.rest.client.internal.async.AsynchronousJiraRestClient;
2619
import com.atlassian.jira.rest.client.internal.async.AtlassianHttpClientDecorator;
2720
import com.atlassian.jira.rest.client.internal.async.DisposableHttpClient;
21+
import com.atlassian.jira.rest.client.internal.json.CimFieldsInfoJsonParser;
22+
import com.atlassian.jira.rest.client.internal.json.GenericJsonArrayParser;
23+
import com.atlassian.jira.rest.client.internal.json.IssueTypeJsonParser;
24+
import com.atlassian.jira.rest.client.internal.json.PageJsonParser;
2825
import com.devexperts.switchboard.api.IntegrationFeatures;
26+
import org.codehaus.jettison.json.JSONArray;
27+
import org.codehaus.jettison.json.JSONException;
28+
import org.codehaus.jettison.json.JSONObject;
2929

3030
import java.net.URI;
31-
import java.util.ArrayList;
32-
import java.util.Collections;
33-
import java.util.HashMap;
34-
import java.util.List;
35-
import java.util.Map;
36-
import java.util.Objects;
37-
import java.util.Set;
31+
import java.util.*;
3832
import java.util.concurrent.TimeUnit;
33+
import java.util.concurrent.atomic.AtomicInteger;
3934
import java.util.stream.Collectors;
4035
import java.util.stream.StreamSupport;
4136

@@ -50,16 +45,21 @@ public class JiraIntegrationFeatures implements IntegrationFeatures {
5045
private final Map<String, Project> projectCache = new HashMap<>();
5146
private final Map<String, CimProject> cimProjectCache = new HashMap<>();
5247
private final Map<String, Map<String, CimIssueType>> projectIssueTypeCache = new HashMap<>();
48+
private final URI serverUri;
5349
private final Map<String, User> usersCache = new HashMap<>();
5450

5551
private final int socketTimeoutSeconds;
5652
private final int searchQueryBatch;
5753

54+
private final DisposableHttpClient httpClient;
55+
5856
JiraIntegrationFeatures(URI serverUri, String username, String password, int socketTimeoutSeconds, int searchQueryBatch) {
57+
this.serverUri = serverUri;
5958
this.socketTimeoutSeconds = socketTimeoutSeconds;
6059
this.searchQueryBatch = searchQueryBatch;
6160
this.authenticationHandler = new BasicHttpAuthenticationHandler(username, password);
62-
this.jiraClient = new AsynchronousJiraRestClient(serverUri, getHttpClient(serverUri, authenticationHandler));
61+
this.httpClient = getHttpClient(serverUri, authenticationHandler);
62+
this.jiraClient = new AsynchronousJiraRestClient(serverUri, httpClient);
6363
}
6464

6565

@@ -72,22 +72,51 @@ public class JiraIntegrationFeatures implements IntegrationFeatures {
7272
*/
7373
public CimIssueType getIssueType(String projectKey, String issueTypeName) {
7474
return projectIssueTypeCache.computeIfAbsent(projectKey, k -> new HashMap<>())
75-
.computeIfAbsent(issueTypeName,
76-
i -> StreamSupport.stream(getCimProject(projectKey).getIssueTypes().spliterator(), false)
77-
.filter(t -> Objects.equals(i, t.getName()))
78-
.findFirst()
79-
.orElseThrow(() -> new IllegalStateException(
80-
String.format("IssueType '%s' not found in project '%s'", issueTypeName, projectKey))));
75+
.computeIfAbsent(issueTypeName,
76+
i -> getIssueTypes(projectKey).stream()
77+
.filter(t -> Objects.equals(i, t.getName()))
78+
.findFirst()
79+
.orElseThrow(() -> new IllegalStateException(
80+
String.format("IssueType '%s' not found in project '%s'", issueTypeName, projectKey))));
8181
}
8282

83-
private CimProject getCimProject(String projectKey) {
84-
return cimProjectCache.computeIfAbsent(projectKey,
85-
k -> StreamSupport.stream(jiraClient.getIssueClient().getCreateIssueMetadata(new GetCreateIssueMetadataOptionsBuilder()
86-
.withExpandedIssueTypesFields()
87-
.withProjectKeys(k)
88-
.build()).claim().spliterator(), false)
89-
.findFirst()
90-
.orElseThrow(() -> new IllegalStateException(String.format("Project '%s' not found", projectKey))));
83+
private final GenericJsonArrayParser<IssueType> issueTypesParser = GenericJsonArrayParser.create(new IssueTypeJsonParser());
84+
private final GenericJsonArrayParser<CimFieldInfo> CIM_ISSUE_TYPE_JSON_PARSER = GenericJsonArrayParser.create(new CimFieldsInfoJsonParser());
85+
86+
87+
private List<CimIssueType> getIssueTypes(String projectKey) {
88+
// calling the Jira REST API directly as JIRA v. 9.x dropped support for createmeta endpoint (https://confluence.atlassian.com/jiracore/preparing-for-jira-9-0-1115661092.html)
89+
try {
90+
String uri = serverUri + "/rest/api/2/issue/createmeta/" + projectKey + "/issuetypes/";
91+
Response issueTypes = httpClient.newRequest(uri).get().get();
92+
PageJsonParser<IssueType> pages = new PageJsonParser<>(issueTypesParser);
93+
Page<IssueType> values = pages.parse(new JSONObject(issueTypes.getEntity()));
94+
return StreamSupport.stream(values.getValues().spliterator(), false).map(i -> {
95+
try {
96+
Response cimIssueTypeRaw = httpClient.newRequest(uri + i.getId()).get().get();
97+
PageJsonParser<CimFieldInfo> cimPages = new PageJsonParser<>(CIM_ISSUE_TYPE_JSON_PARSER);
98+
JSONObject json = new JSONObject(cimIssueTypeRaw.getEntity());
99+
Page<CimFieldInfo> cimValues = cimPages.parse(json);
100+
AtomicInteger index = new AtomicInteger(0);
101+
JSONArray array = json.getJSONArray("values");
102+
Map<String, CimFieldInfo> fields = StreamSupport.stream(cimValues.getValues().spliterator(), false).map(c -> {
103+
// taking the fieldId directly from JSON as it is not bound to the CimFieldInfo object
104+
try {
105+
String id = ((JSONObject) array.get(index.getAndIncrement())).get("fieldId").toString();
106+
return new CimFieldInfo(id, c.isRequired(), c.getName(), c.getSchema(), c.getOperations(), c.getAllowedValues(), c.getAutoCompleteUri());
107+
} catch (JSONException e) {
108+
throw new RuntimeException(e);
109+
}
110+
}).collect(Collectors.toMap(CimFieldInfo::getName, f -> f));
111+
112+
return new CimIssueType(i.getIconUri(), i.getId(), i.getName(), i.isSubtask(), i.getDescription(), i.getIconUri(), fields);
113+
} catch (Exception e) {
114+
throw new RuntimeException(e);
115+
}
116+
}).collect(Collectors.toList());
117+
} catch (Exception e) {
118+
throw new RuntimeException(e);
119+
}
91120
}
92121

93122
/**
@@ -99,13 +128,13 @@ private CimProject getCimProject(String projectKey) {
99128
*/
100129
public BasicComponent getComponent(String projectKey, String componentName) {
101130
return StreamSupport.stream(projectCache.computeIfAbsent(projectKey,
102-
p -> jiraClient.getProjectClient().getProject(p).claim())
103-
.getComponents()
104-
.spliterator(), false)
105-
.filter(i -> Objects.equals(i.getName(), componentName))
106-
.findFirst()
107-
.orElseThrow(
108-
() -> new IllegalStateException(String.format("Component '%s' not found in project '%s'", componentName, projectKey)));
131+
p -> jiraClient.getProjectClient().getProject(p).claim())
132+
.getComponents()
133+
.spliterator(), false)
134+
.filter(i -> Objects.equals(i.getName(), componentName))
135+
.findFirst()
136+
.orElseThrow(
137+
() -> new IllegalStateException(String.format("Component '%s' not found in project '%s'", componentName, projectKey)));
109138
}
110139

111140
/**
@@ -137,8 +166,8 @@ public List<Issue> searchForIssues(String jqlQuery) {
137166
*/
138167
public List<String> searchForIssueKeys(String jqlQuery) {
139168
return searchForIssues(jqlQuery, Collections.emptySet())
140-
.stream().map(BasicIssue::getKey)
141-
.collect(Collectors.toList());
169+
.stream().map(BasicIssue::getKey)
170+
.collect(Collectors.toList());
142171
}
143172

144173
/**
@@ -175,11 +204,11 @@ private List<Issue> searchForIssues(String jqlQuery, Set<String> fields) {
175204
private List<Issue> searchForIssues(String jqlQuery, Integer limit, Integer startAt, Set<String> fields) {
176205
try {
177206
return StreamSupport.stream(jiraClient.getSearchClient()
178-
.searchJql(jqlQuery, limit, startAt, fields)
179-
.claim()
180-
.getIssues()
181-
.spliterator(), false)
182-
.collect(Collectors.toList());
207+
.searchJql(jqlQuery, limit, startAt, fields)
208+
.claim()
209+
.getIssues()
210+
.spliterator(), false)
211+
.collect(Collectors.toList());
183212
} catch (Exception e) {
184213
throw new RuntimeException(String.format("Failed to execute query '%s'", jqlQuery), e);
185214
}

Diff for: integrations/jira/src/main/java/com/devexperts/switchboard/integrations/jira/XRayGenericTestsCreatingConsumer.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ private IssueInput createInput(Test test) {
215215
}
216216

217217
private IssueInputBuilder setField(Test test, IssueInputBuilder builder, String fieldName, TestValuesExtractor valuesExtractor,
218-
Map<String, CimFieldInfo> fields)
218+
Map<String, CimFieldInfo> fields)
219219
{
220220
String value = valuesExtractor.getTestValue(test);
221221
if (value == null) {
@@ -365,4 +365,4 @@ public String getIdentifier() {
365365

366366
@Override
367367
public void close() {/*do nothing*/}
368-
}
368+
}

0 commit comments

Comments
 (0)