How to Update Salesforce Case Fields Based on Jira Issue Update

Sep 1, 2015 | JIRA, Salesforce

An example of how to write a trigger on the zAgileConnect ZIssue custom object in Salesforce.  The trigger may be used to perform specific actions on a Case based upon specific Issue events (such as change in Status, Assignee, etc.).

Please note that while we offer this as a guide, customizations based on zAgileConnect objects and resources are not supported by zAgile unless performed directly by zAgile.

Create New Trigger

Go to developer console and click on File/New/Apex Trigger. Give a name to your trigger, select the object ZIssue__c and submit.

The object ZIssue is shown with the prefix ‘zsfjira’, then you find it as ‘zsfjira__ZIssue__c’. If the object ZIssue is not visible contact your administrator for profile apex classes access permissions.

Basic Trigger Body

As soon as you create the new Trigger, the new Apex trigger is registered in Salesforce and already active. Salesforce writes a basic body for your Trigger:

Body
trigger ZIssueCustomTrigger on zsfjira__ZIssue__c (before insert) {
}

 

We highly recommend that you use the Trigger in AFTER events in order to minimize any impact on ZIssue update.  A Before event may cause an exception in DML operation, causing data inconsistencies between Salesforce and JIRA.  Furthermore, you must also take extra care to handle any exceptions that are generated in this trigger, to ensure that updates to ZIssue (coming from JIRA) do not fail.

Your Trigger declaration should be as follows:

Body
trigger ZIssueCustomTrigger on zsfjira__ZIssue__c (after insert, after update, after delete) {

}

Events Based on ZIssue

The following table describes events that will cause a DML operation on ZIssue object:

Event
Happens When
Insert Linking an Issue that does no exists on ZIssue.
Update When updating an existing Issue on ZIssue through JIRA or Salesforce (Update is done only if at least one mapped field is updated, this mean this event is fired also when: performing transitions, setting users, moving issues to different project, etc). Please note that zAgileConnect performs updates on ZIssue  on non Issue related fields, like internal flags. These updates should not execute any action in your trigger, as these updates are not JIRA Issue updates. You should look at fields updated in ZIssue and only execute any action if the updated issue field is relevant to you.
Delete When deleting an existing Issue in ZIssue through JIRA or Salesforce
Undelete Is never fired by zAgileConnect. It should not be implemented.

Getting Cases related to Issues

The context of ZIssue trigger is the mapped JIRA Issue fields.  To get additional information related to the Issues (ex: Cases related to the Issue), you will need to execute a SOQL.

The following SOQL returns the Cases related to an Issues in a List form:

SOQL
SELECT Id,zsfjira__IssueKey__c,(SELECT zsfjira__CaseId__r.CaseNumber FROM zsfjira__ZIssue_Case__r)FROM zsfjira__ZIssue__c WHERE Id IN(SELECT zsfjira__ZIssueId__c FROM zsfjira__ZIssue_Case__c)
 
 

We would use same SOQL query to get related Cases of updated issues (note that condition was set in the SOQL query for filtering only the updated/inserted issues, Trigger.newMap.keySet())

Trigger Body
trigger ZIssueCustomTrigger on zsfjira__ZIssue__c (after insert,after update,after delete) {
    if(trigger.isUpdate||trigger.isInsert){
        try{//It is mandatory that you wrap all your trigger code in try and catch statements
            for(zsfjira__ZIssue__c issue:[SELECT Id,zsfjira__IssueKey__c,(SELECT zsfjira__CaseId__r.CaseNumber FROM zsfjira__ZIssue_Case__r)FROM zsfjira__ZIssue__c WHERE Id IN: Trigger.newMap.keySet()]){
                System.debug('Issue: '+issue.zsfjira__IssueKey__c+', Related Cases: ');
                for(zsfjira__ZIssue_Case__c rel:issue.zsfjira__ZIssue_Case__r){
                    System.debug('Case Number:' + rel.zsfjira__CaseId__r.CaseNumber+', Case Id: '+rel.zsfjira__CaseId__c);
                }
            }
        }catch(Exception exe){
            //handle any error executing your trigger, error logs, send email, etc...
        }
    }
}
 

Error Handling

Handling all the trigger exceptions is critical. Trigger exceptions not handled could impact Issue updates in Salesforce, partially disabling the functionality of zAgileConnect.

Custom trigger should filter execution based on updated fields

 Any custom trigger on ZIissue events must be executed AFTER UPDATE/INSERT to avoid problems updating issues in salesforce and should use Trigger.newMap, Trigger.oldMap to filter only updates on ZIssue fields of interest (for instance if you are writing a trigger that updates a case field based on JIRA issue status update, you need to make sure that the JIRA status field was updated, and not other field). It is because we have some fields that we use as flags in ZIssue custom object and we update them grammatically any time, these updates of course does not mean JIRA issue updates and should not trigger any execution (for instance, your trigger should not update any case field when our internal flags are updated on ZIssue)

Performing DML in the Trigger

As mentioned previously, any non handled exception will cause the trigger to fail and ZIssue object to become outdated with JIRA. As a consequence, some zAgileConnect features will not work as expected. The most common causes of exceptions given during the trigger are DML operations specially if the related Object has triggers. Please follow this recommendations in order to avoid this problem:

  1.   Surround your DML operation with try and catch to avoid impacting ZIssue Object if any error occurs:
    try{
        update cases;
    } catch (DmlException d){
        System.debug('Exception during DML operation: ' + d.getMessage());
    }
  2. Use Database.update(List<SObject>, false) with SaveResult[] to allow partial updates (update all the record that can be updated so if any individual record update fails, all will not fail)
    Database.SaveResult[] lsr = Database.update(cases, false);
     
    for(Database.SaveResult sr : lsr){
        if (!sr.isSuccess()) {
            myMethodToaddToErrorObjectList(sr);
        }
    }

We recommend you use both best practices in your trigger. check Salesforce documentation for further details: https://developer.salesforce.com/page/An_Introduction_to_Exception_Handling

Testing the Trigger

For testing the trigger please follow these considerations:

  • The ZIssue record when is created is not related to any Case yet.
  • For testing a ZIssue insertion, you will need required fields IssueKey__c and IssueId__c for testing purpose you can fill them with any values, also the Name field must be the Issue key.
  • For inserting to ZIssue_SF (junction object) you will need to set the IssueId of the JIRA issue which belongs the relation to the ZIssue_SF field IssueId__c, other consideration to take is filling the field IssueCreated__c which is a boolean that indicates if the issue was created from the related case, otherwise it was just linked. finally fill the field zsfjira__ZIssue__c with the SF record ID of ZIssue and  zsfjira__Case__c with de SF Case record ID.

This is an example to test the trigger on a inserting and updating scenario, you may need to assert your results according to your trigger logic.

Trigger Unit Test
@isTest
public class ZIssueCustomTriggerTest {
    static testMethod void testTrigger() {
        //--INSERT
        zsfjira__ZIssue__c ziss = new zsfjira__ZIssue__c();
        ziss.zsfjira__IssueId__c = 1002;
        ziss.Name=ziss.zsfjira__IssueKey__c = 'ABM-2';
        ziss.Name=ziss.zsfjira__Status__c = 'Open';
        insert ziss;
        
        Case caseTest = new Case();
        caseTest.Subject = 'Case Test';
        insert caseTest;
        
        zsfjira__ZIssue_SF__c rel = new zsfjira__ZIssue_SF__c();
        rel.zsfjira__IssueId__c = 1002;
        rel.zsfjira__ZIssue__c = ziss.Id;
        rel.zsfjira__Case__c = caseTest.Id;
        rel.zsfjira__IssueCreated__c = false;
        insert rel;       
        
        System.assert(ziss!=null);
        //--UPDATE
        ziss = [SELECT Id,zsfjira__Status__c FROM zsfjira__ZIssue__c WHERE zsfjira__IssueKey__c='ABM-2'];
        ziss.zsfjira__Status__c = 'Closed';
        upsert ziss;
        System.assert(ziss!=null);
        
    }
}
Tags:

> You Might Also Like

Learn How Customer Support Teams Overcome Salesforce and Jira Integration Challenges – Get the White Paper!

Learn How Customer Support Teams Overcome Salesforce and Jira Integration Challenges – Get the White Paper!

Customer support teams commonly struggle with the tedious yet critical task of escalating issues to engineering, tracking their progress, and turning the responses around to their customers in a timely manner. It typically involves navigating back and forth between Salesforce and Jira, copying and pasting information between the two applications, and manually checking the progress of Jira Issues.
An ideal solution would involve integrating Salesforce with Jira to reduce the need for support agents to navigate back and forth between the two applications.

Loading...