Unable to POST and PUT using OAuth for REST APIs

I was able to GET and DELETE, but I was not able to POST or PUT. I was able to make all calls using Basic Authentication but not OAuth. I followed the tutorial from https://developer.atlassian.com/cloud/jira/platform/jira-rest-api-oauth-authentication/ . The example only uses GET. I used the same API for POST, PUT, and DELETE which is required to create, edit and delete a a JIRA issue.

I get the com.google.api.client.http.HttpResponseException: 400 Bad Request
{"errorMessages":["Can not instantiate value of type [simple type, class com.atlassian.jira.rest.v2.issue.IssueUpdateBean] from JSON String; no single-String constructor/factory method"]}
It appears to be a common problem from a quick Google search, but I am unable to find a solution. Could you point me to the right resources to make it work – forums or other source of development help.
For example, I tried to make a POST call to create an issue passing in this JSON:

{
  "fields": {
    "summary": "JUNIT testCreateDeleteIssue() Tue Oct 03 13:57:25 EDT 2017",
    "issuetype":
      { "name": "Bug" },
    "project":
      { "key": "HELLO" }
  }
}

I get the following error:

com.google.api.client.http.HttpResponseException: 400 Bad Request
{"errorMessages":["Can not instantiate value of type [simple type, class com.atlassian.jira.rest.v2.issue.IssueUpdateBean] from JSON String; no single-String constructor/factory method"]}
	at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1070)

Code use to create HttpContent:
HttpContent content = new JsonHttpContent(new JacksonFactory(), jsonString);

Code to POST

HttpRequestFactory requestFactory = nt.createRequestFactory(parameters);
HttpRequest request = requestFactory.buildPostRequest(jiraUrl, content);
request.execute();
1 Like

From the docs:

The fields, that can be set on an issue create operation, can be determined using the /rest/api/2/issue/createmeta resource. If a particular field is not configured to appear on the issue’s Create screen, then it will not be returned in the createmeta response. A field validation error will occur if such field is submitted in request.

Have you called createmeta to ensure that you have a “Bug” issuetype?

Also in the example for create issue the issueType is being passed an id of the issue type instead of the name.

{
    "update": {
        "worklog": [
            {
                "add": {
                    "timeSpent": "60m",
                    "started": "2011-07-05T11:05:00.000+0000"
                }
            }
        ]
    },
    "fields": {
        "project": {
            "id": "10000"
        },
        "summary": "something's wrong",
        "issuetype": {
            "id": "10000"
        },
        "assignee": {
            "name": "homer"
        },
        "reporter": {
            "name": "smithers"
        },
        "priority": {
            "id": "20000"
        },
        "labels": [
            "bugfix",
            "blitz_test"
        ],
        "timetracking": {
            "originalEstimate": "10",
            "remainingEstimate": "5"
        },
        "security": {
            "id": "10000"
        },
        "versions": [
            {
                "id": "10000"
            }
        ],
        "environment": "environment",
        "description": "description",
        "duedate": "2011-03-11",
        "fixVersions": [
            {
                "id": "10001"
            }
        ],
        "components": [
            {
                "id": "10000"
            }
        ],
        "customfield_30000": [
            "10000",
            "10002"
        ],
        "customfield_80000": {
            "value": "red"
        },
        "customfield_20000": "06/Jul/11 3:25 PM",
        "customfield_40000": "this is a text field",
        "customfield_70000": [
            "jira-administrators",
            "jira-software-users"
        ],
        "customfield_60000": "jira-software-users",
        "customfield_50000": "this is a text area. big text.",
        "customfield_10000": "09/Jun/81"
    }
}

Try that and let me know if that works for you?

Thanks,
Ralph

I will try within the hour. But to let you know, I pass in the exact info using basic authentication and it works. It just doesnt work for OAuth using the same libs in the tutorial. I am curious why the tutorial only show GET calls and not the others.

I received the exact same error. Is that error generated from server or the client?

Do you have sample code for a POST call for the linked tutorial? That tutorial only shows GET calls.

anymore ideas? Curious to know why the tutorial doesn’t have a POST example when it is clearly needed to create a JIRA issue.

Hi, @alex.phung.

I created a rough example based on what you started with, and was able to make it work. For the JSON string, I used GenericData like these instead of a String:

        GenericData myData = new GenericData();
        
        GenericData projectData = new GenericData();
        projectData.put("key", "HELLO");

        GenericData issueTypeData = new GenericData();
        issueTypeData.put("name", "Bug");        
        
        GenericData fieldsData = new GenericData();
        fieldsData.set("summary", "TEST SUMMARY");
        fieldsData.set("issuetype", issueTypeData);
        fieldsData.set("project", projectData);
        
        myData.put("fields", fieldsData);

For the HttpContent:

HttpContent content = new JsonHttpContent(new JacksonFactory(), myData);

That should solve the challenges you faced. Cheers!
Ian

1 Like

It works. Thank you. Can you point me to the documentation for GenericData and its use. I am looking for a better way to generate GenericData or JsonData from a JSON string or JSON Object.

Edit – actually, I was able to make this work by converting the JSON string into a JSON object.

Glad you made it work @alex.phung. Yes, JSONObject is also a valid (and sometimes a cleaner) approach.

In order to help other people who might experience the same problem, kindly mark the answer to guide them. Thanks!

I use com.google.gson.Gson to convert objects to/from JSON:
private final Gson GSON = new GsonBuilder().setPrettyPrinting().create();

Instead of passing in a string or GenericData, I pass in a JSON object. Convert the JSON string into Object.class:
Object jsonObject = GSON.fromJson(jsonString, Object.class);
HttpContent content = new JsonHttpContent(new JacksonFactory(), jsonObject);

This is a little awkward in converting an object (e.g., JIRAIssue) to a JSON string and then back to an OBJECT, but I have existing code that passing in a string to POST/PUT when using basic authentication. I may refactor my code to cleanly handle both basic authentication and OAuth later.

Code to POST (or PUT) is the same:
HttpRequestFactory requestFactory = nt.createRequestFactory(parameters);
HttpRequest request = requestFactory.buildPostRequest(jiraUrl, content);
request.execute();

I confirm that this solution works.

1 Like

In order to help people, I’ll soon provide full source code with spring boot application.
For now, please see this : https://stackoverflow.com/a/59981597/1551368