我有一个将 Jira 集成到公司应用程序中的请求。请求是使用 OAuth,并且能够使用 Jira API,并带有重音以使用“创建问题”调用。
我稍后会提供源代码,只是为了强调使用 POST 调用时我遇到了 json 问题,我必须使用 com.google.api.client.util.GenericData 才能正确创建问题。
代码摘录:
@PropertySource("classpath:/JiraApiCalls/calls.properties")
@Service
public class JiraService {
//<editor-fold desc="infra">
@Autowired
JiraClient jiraClient;
//<editor-fold desc="Api Business Calls">
@Value("${GET_ISSUE_BY_KEY_URL}")
String apiCallIssueByKey;
@Value("${SITE_ID_AND_PORTFOLIO_SEARCH_JQL_WITH_OR}")
String apiCallSiteIdAndPortfolioSearchJQLWithOr;
@Value("${OR_SITE_ID}")
String apiCallOrSiteId;
@Value("${SEARCH_ISSUES_URL}")
String searchIssuesKey;
@Value("${DASHBOARDS}")
String apiCallAllDashboard;
@Value("${PROJECTS}")
String apiCallAllProjects;
@Value("${PROJECT}")
String apiCallProjectById;
@Value("${ISSUETYPES}")
String apiCallAllIssueTypes;
@Value("${ISSUETYPE}")
String apiCallApiIssueType;
@Value("${ISSUE_CREATE}")
String apiCallIssueCreate;
//</editor-fold>
//<editor-fold desc="Definitions : Jira concrete usage">
static final List<String> ISSUE_FIELDS = Arrays.asList(
"status", "creator", "reporter", "assignee", "description",
"summary", "customfield_11110", "customfield_11126", "components"
);
public JiraSingleResultIssueDto getIssueByKey(String key) {
String issueApiMethodCallUrl = MessageFormat.format( apiCallIssueByKey, key );
JiraSingleResultIssueDto dto = jiraClient.executeGet( JiraSingleResultIssueDto.class, issueApiMethodCallUrl );
return dto;
}
public AllDashboardsDto getAllDashboards() {
return jiraClient.executeGet( AllDashboardsDto.class, apiCallAllDashboard );
}
public List<ProjectDto> getAllProjects() {
List<ProjectDto> projects = jiraClient.executeGetExpectingList( apiCallAllProjects );
return projects;
}
public ProjectDto getProjectByKey(Object key) {
ProjectDto project = jiraClient.executeGet( ProjectDto.class, MessageFormat.format( apiCallProjectById, String.valueOf( key ) ) );
return project;
}
public List<JiraIssueTypeDto> getAllIssueTypes() {
List<JiraIssueTypeDto> issueTypes = jiraClient.executeGetExpectingList( apiCallAllIssueTypes );
return issueTypes;
}
public JiraIssueTypeDto getIssueType(Object key) {
JiraIssueTypeDto issueType = jiraClient.executeGet( JiraIssueTypeDto.class, MessageFormat.format( apiCallApiIssueType, String.valueOf( key ) ) );
return issueType;
}
public IssueCreatedResponseDto createIssue(IssueDto issueDto) throws Exception {
GenericData issueData = new GenericData();
try {
// check for existing Project, and carry on if it exists...
ProjectDto projectDto = getProjectByKey( issueDto.getFields().getProject().getId() );
GenericData projectData = new GenericData();
projectData.put( "key", projectDto.getKey() );
// check for existing issue type, and carry on with no errors..
Long issueId = issueDto.getFields().getIssuetype().getId();
getIssueType( issueId );
GenericData issueTypeData = new GenericData();
issueTypeData.put( "id", issueId );
GenericData fieldsData = new GenericData();
fieldsData.set( "summary", issueDto.getFields().getSummary() );
fieldsData.set( "description", issueDto.getFields().getDescription() );
fieldsData.set( "issuetype", issueTypeData );
fieldsData.set( "project", projectData );
issueData.put( "fields", fieldsData );
IssueCreatedResponseDto issueResponse = jiraClient.executePost( IssueCreatedResponseDto.class, apiCallIssueCreate, issueData );
return issueResponse;
} catch (Exception e) {
throw new Exception( e );
}
}
}
Jira 客户端:
@Component
public class JiraClient {
private static Logger LOGGER = Logger.getLogger( JiraClient.class.getName() );
//<editor-fold desc="oauth 1.0 credentials">
@Value("${jira_home}")
String JIRA_HOME_URL;
@Value("${jira_base_url}")
String JIRA_ENDPOINT_URL;
@Value("${jira_access_token}")
String JIRA_ACCESS_TOKEN;
@Value("${jira_secret}")
String JIRA_SECRET_KEY;
@Value("${jira_consumer_key}")
String JIRA_CONSUMER_KEY;
@Value("${jira_private_key}")
String JIRA_PRIVATE_KEY;
//</editor-fold>
@Value("${datetimeformat}")
private String dateTimeFormat;
JSONUtils jsonUtils;
JiraOAuthClient jiraOAuthClient;
@PostConstruct
void jiraOAuthClientInit() {
if (jiraOAuthClient == null) {
try {
jiraOAuthClient = new JiraOAuthClient( JIRA_HOME_URL );
} catch (Exception e) {
String errMsg = "Jira OAuth Client Error.";
LOGGER.log( Level.WARNING, errMsg, e );
throw new RuntimeException( errMsg + e );
}
}
jsonUtils = new JSONUtils( dateTimeFormat );
}
//<editor-fold desc="Infra : Basic Get/Post Request support methods">
public HttpResponse handleGetRequest(String apiMethodCallUrl) {
try {
OAuthParameters parameters = jiraOAuthClient.getParameters( JIRA_ACCESS_TOKEN, JIRA_SECRET_KEY, JIRA_CONSUMER_KEY, JIRA_PRIVATE_KEY );
HttpResponse response = getResponseFromUrl( parameters, new GenericUrl( apiMethodCallUrl ) );
return response;
} catch (Exception e) {
String errMsg = "Handle GetRequest Error.";
LOGGER.log( Level.WARNING, errMsg, e );
return null;
}
}
public HttpResponse handlePostRequest(String apiMethodCallUrl, HttpContent requestContent) {
try {
OAuthParameters parameters = jiraOAuthClient.getParameters( JIRA_ACCESS_TOKEN, JIRA_SECRET_KEY, JIRA_CONSUMER_KEY, JIRA_PRIVATE_KEY );
HttpResponse response = postResponseFromUrl( parameters, new GenericUrl( apiMethodCallUrl ), requestContent );
return response;
} catch (Exception e) {
String errMsg = "Handle PostRequest Error.";
LOGGER.log( Level.WARNING, errMsg, e );
return null;
}
}
private HttpResponse getResponseFromUrl(OAuthParameters parameters, GenericUrl jiraUrl) throws IOException {
HttpRequestFactory requestFactory = new NetHttpTransport().createRequestFactory( parameters );
HttpRequest request = requestFactory.buildGetRequest( jiraUrl );
return request.execute();
}
private HttpResponse postResponseFromUrl(OAuthParameters parameters, GenericUrl jiraUrl, HttpContent requestContent) throws IOException {
HttpRequestFactory requestFactory = new NetHttpTransport().createRequestFactory( parameters );
HttpRequest request = requestFactory.buildPostRequest( jiraUrl, requestContent );
return request.execute();
}
//</editor-fold>
//<editor-fold desc="Advanced Get/Post methods">
//<editor-fold desc="Generic universal call/response">
private HttpResponse executeGetAndReturnHttpResponse(@NonNull String apiMethodCallUrl) {
return handleGetRequest( JIRA_ENDPOINT_URL + apiMethodCallUrl );
}
//</editor-fold>
/**
* Custom GET call, expecting result of a type T<br>
*
* @param apiMethodCallUrl Url defined by the user.<br>
* Usage example :<br>
* Api call, and two parameters defined at {0} and {1} positions:<br>
* SITE_ID_AND_PORTFOLIO_SEARCH_JQL_WITH_OR=Portfolio = {0} AND ("Site ID" ~ "0"{1})<br>
* For proper usage, MessageFormat.format( apiCall_Name, apiCall_Parameters) may be used.<br>
*/
public <T> T executeGet(Class<T> clazz, String apiMethodCallUrl) {
try {
HttpResponse jsonResponse = executeGetAndReturnHttpResponse( apiMethodCallUrl );
if (jsonResponse == null) {
return null;
}
return jsonUtils.parseResponse( jsonResponse, clazz );
} catch (Exception e) {
String errMsg = "Executing Get Request Error.";
LOGGER.log( Level.SEVERE, errMsg, e );
throw new RuntimeException( errMsg, e );
}
}
//<editor-fold desc="Default GET call with path variables injected into call, for returning Lists of objects">
/**
* Custom GET call, expecting list result.<br>
*
* @param apiMethodCallUrl Url defined by user.<br>
* Usage example :<br>
* Api call, with no parameters defined in api call "apiCallAllProjects",<br>
* so there is no need for formating rest method call with parameters.<br>
* If there was a need, look at {@link JiraClient#executeGet)
*/
public <T> List<T> executeGetExpectingList(@NonNull String apiMethodCallUrl) {
try {
HttpResponse jsonResponse = executeGetAndReturnHttpResponse( apiMethodCallUrl );
if (jsonResponse == null) {
return null;
}
return jsonUtils.parseResponseAsList( jsonResponse );
} catch (Exception e) {
String errMsg = "Executing Get Request Error.";
LOGGER.log( Level.SEVERE, errMsg, e );
throw new RuntimeException( errMsg, e );
}
}
//</editor-fold>
//<editor-fold desc="POST">
public HttpResponse executePostRequest(@NonNull String postOperationName, @NonNull GenericData contentGenericData) {
String apiCallUrlPath = JIRA_ENDPOINT_URL + postOperationName;
try {
OAuthParameters parameters = jiraOAuthClient.getParameters( JIRA_ACCESS_TOKEN, JIRA_SECRET_KEY, JIRA_CONSUMER_KEY, JIRA_PRIVATE_KEY );
HttpContent content = new JsonHttpContent( new JacksonFactory(), contentGenericData );
HttpResponse response = postResponseFromUrl( parameters, new GenericUrl( apiCallUrlPath ), content );
return response;
} catch (HttpResponseException hre) {
String errMsg = "Executing Post Request Error. " + hre;
LOGGER.log( Level.SEVERE, errMsg, hre );
throw new RuntimeException( errMsg, hre );
} catch (Exception e) {
String errMsg = "Executing Get Request, no result.";
LOGGER.log( Level.INFO, errMsg, e );
throw new RuntimeException( errMsg, e );
}
}
public <T> T executePost(Class<T> clazz, @NonNull String postOperationName, @NonNull GenericData contentGenericData) {
try {
HttpResponse jsonResponse = executePostRequest( postOperationName, contentGenericData );
if (jsonResponse == null) {
return null;
}
return jsonUtils.parseResponse( jsonResponse, clazz );
} catch (Exception e) {
String errMsg = "Executing Post Request Error.";
LOGGER.log( Level.WARNING, errMsg, e );
throw new RuntimeException( errMsg, e );
}
}
//</editor-fold>
//</editor-fold>
}