Java - HTTP Post Jira API - Bad Request
Asked Answered
C

2

3

I have this code to do a HTTP Post to a Jira URL (https://xxxxxxx.atlassian.net/rest/api/2/issue/):

    Object jsonMessage = arg0.getMessage().getPayload();

    URL url = new URL(jiraUrl + jiraIssuePath);

    HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();

    BASE64Encoder enc = new sun.misc.BASE64Encoder();
    String userpassword = jiraUsername + ":" + jiraPassword;
    String encodedAuthorization = enc.encode(userpassword.getBytes());
    conn.setDoOutput(true);
    conn.setDoInput(true);
    conn.setRequestProperty("Authorization", "Basic " + encodedAuthorization);
    conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");

    conn.setRequestMethod("POST");

    OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
    wr.write(jsonMessage.toString());
    wr.flush();

    StringBuilder sb = new StringBuilder();
    int HttpResult = conn.getResponseCode();
    if (HttpResult == HttpsURLConnection.HTTP_OK) {
        BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
        String line = null;
        while ((line = br.readLine()) != null) {
            sb.append(line + "\n");
        }
        br.close();
        System.out.println("" + sb.toString());
    } else {
        System.out.println(conn.getResponseMessage());
    }

If I use a HTTP Get without JSON message it works fine, but if I use a POST sending a JSON message it return me this error:

java.io.IOException: Server returned HTTP response code: 400 for URL: https://xxxxxxx.atlassian.net/rest/api/2/issue/

I use Postman App to check headers(Content-Type and Authorization) and body and with that App it create the issue in Jira.

Added: If I inspect the connection it has the parameter Method like GET instead of POST.

What can I be doing wrong?

Chare answered 31/8, 2016 at 11:11 Comment(4)
Maybe the rest API can only accesed with get?Backhander
No, because if I do the POST with Postman App it works fine.Chare
Check body of responce. Maybe it bring some light on cause of problem.Drinking
If I Inspect the connection it has the request method like "GET" instead of "POST" How to be that if I define the request like post?Chare
T
0

Can you show the 400 response detail?

I have tried some key code and made a POST request successfully. JIRA server will return very detailed message for 400 response like

{
    "errorMessages": [
        "Field 'priority' is required"
    ],
    "errors": {}
}

This answer may be useful about how to make a post request. Java - sending HTTP parameters via POST method easily

Tautonym answered 10/9, 2016 at 11:45 Comment(0)
U
0

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.

Code excerpt :

@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 client :

@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>
}
Unpriced answered 30/1, 2020 at 8:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.