且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Java-HTTP Post Jira API-错误的请求

更新时间:2021-10-09 22:27:22

我有一个将Jira集成到公司应用程序中的请求.请求是使用OAuth,并能够使用Jira API,并带有重音以使用创建问题"调用. 稍后我将提供源代码,以强调使用POST调用时遇到了json问题,并且必须使用com.google.api.client.util.GenericData才能正确创建问题.

I had a request to integrate Jira into company application. The request is to use OAuth, and to be able to use Jira API, with accent to use "create issue" call. I'll provide source later, just to emphasize that for use a POST call I've encountered problems with json, and I had to use com.google.api.client.util.GenericData in order to make proper creation of issue.

代码摘录:

@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>
}