0

I am trying to get the JIRA issue details onto the salesforce Case object. I followed the documentation and I created to Apex classes and One VisualForce page.

I am getting the error on the visual force page section : Content cannot be displayed: Malformed JSON: Expected '[' at the beginning of List/Set.

What would be wrong in my code? Any ideas?

Following are my codes for this project:

JIRA fetch

public class JIRAFetchIssuesController {

private String issuesJson;

// Constructor of this class. Note that a request will be sent to JIRA when this class is constructed.
public JIRAFetchIssuesController(ApexPages.StandardController stdController) {
    Case theCase = (Case)stdController.getRecord();
    this.issuesJson = getResultJson('Case', theCase.id);
}

// Sends request to JIRA and returns the request body which should be a valid JSON.
private static String getResultJson(String objectType, String objectId) {
    try {
        HttpRequest req = buildRequest(JIRA.baseUrl, JIRA.username, JIRA.password, JIRA.systemId, objectType, objectId);
        HttpResponse res = JIRA.sendRequest(req);
        return res.getBody();
    } catch(System.CalloutException e) {
        System.debug(e);
        return '';
    }
}

// Constructs request needed to fetch JIRA issues from provided parameters.
@testVisible private static HttpRequest buildRequest(String baseUrl, String username, String password,
                                 String systemId, String objectType, String objectId) {
    HttpRequest req = new HttpRequest();
    String basicAuthHeader = JIRA.authHeader(username, password);
    String endpoint = getEndpoint(baseUrl, systemId, objectType, objectId);
    req.setHeader('Authorization', basicAuthHeader);
    req.setHeader('Content-Type','application/json');
    req.setMethod('GET');
    req.setEndpoint(endpoint);
    return req;
}

// Creates the endpoint to fetch the issue from provided parameters.
private static String getEndpoint(String baseUrl, String systemId, String objectType, String objectId) {
    return baseUrl + '/rest/customware/connector/1.0/' + systemId + '/' + objectType + '/' + objectId + '/issue/fetch.json';
}

public String getIssuesJSON() {
    return this.issuesJson;
}

public List<JIRAIssue> getIssues() {
    return (List<JIRAIssue>)JSON.deserialize(this.issuesJson , List<JIRAIssue>.class);
}

// JIRA Issue Object.
@testVisible class JIRAIssue {

    public String summary { get; }
    public String project { get; }
    public String reporter { get; }
    public String key { get;}
    public String status { get; }
    public String resolution { get; }
    public String url { get; }
    public String type { get; }
    public String assignee { get; }
    public String description { get; }
    public String priority { get; }
    public String due_date { get; }

}

}

JIRA public with sharing class JIRA {

// Change values in this class according to you JIRA/Salesforce coordinates.

public static String baseUrl = 'http://jira.hdquotecenter.com/'; // Base URL of your JIRA instance
public static String systemId = '2'; // Salesforce Connector System ID in JIRA
public static String username = 'venkatdavuluri';  // JIRA username
public static String password = 'Wildcraft@987'; // JIRA password

public static String agentProfileName = 'JIRA Agent'; // Jira agent profile name in Salesforce

// Constructs Basic Http Authentication header from provided credentials
public static String authHeader(String u, String p) {
    Blob headerValue = Blob.valueOf(u + ':' + p);
    return 'Basic ' + EncodingUtil.base64Encode(headerValue);
}

// Sends a request and returns the response
public static HttpResponse sendRequest(HttpRequest req) {
    Http http = new Http();
    return http.send(req);
}

// Detects whether current user is not JIRA agent. By calling this you can make sure that
// infinite loops won't happen in triggers (for instance when synchronizing an issue with JIRA)
public static Boolean currentUserIsNotJiraAgent() {
    Boolean allow = false;
    List<Profile> jiraAgentProfile = [SELECT Id FROM Profile WHERE Name=:JIRA.agentProfileName];
    if (!jiraAgentProfile.isEmpty()) {
        String jiraProfileAgentId = String.valueOf(jiraAgentProfile[0].id);
        allow = UserInfo.getProfileId() != jiraProfileAgentId;
    }
    return allow || Test.isRunningTest();
}

}

VF PAGE

<apex:pageblock title="JIRA Issues" rendered="{!Issues.size > 0}">
<!-- Create table for JIRA issues. With  -->
    <apex:pageBlockTable value="{!Issues}" var="issue">
        <!-- Issue Key column -->
        <apex:column headerValue="Issue Key">
            <!-- Make it link to JIRA Issue -->
            <apex:outputLink value="{!issue.url}" target="_blank">{!issue.key}</apex:outputLink>
        </apex:column>
        <!-- Issue Resolution column -->
        <apex:column headerValue="Resolution" value="{!issue.resolution}"/>
        <!-- Issue Status column -->
        <apex:column headerValue="Status" value="{!issue.status}" />
        <!-- Issue Assignee column -->
        <apex:column headerValue="Assignee" value="{!issue.assignee}" />
    </apex:pageBlockTable>
</apex:pageblock>

<apex:pageblock title="JIRA Issues" rendered="{!Issues.size == 0}">
    <apex:outputLabel >No JIRA Issue associated with this Case</apex:outputLabel>
</apex:pageblock>

1 Answer 1

5

This code:

return (List<JIRAIssue>)JSON.deserialize(this.issuesJson, List<JIRAIssue>.class);

requires that the JSON is an array at its root (starts with [) but it appears that in your code it does not.

I suggest you System.debug(issuesJson); immediately before that line and see what the JSON format is. There may be a root object that has a name that holds the array. Or check the documentation for the end point you are using.

2
  • Should I put it in front of the return or (List<JIRAIssue>)?
    – abhi
    Feb 3, 2017 at 14:31
  • I got the Answer. I had a blackslash on the endpoint URL in the remote site settings. I figured it out.
    – abhi
    Feb 3, 2017 at 21:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .