2012-07-20 5 views
1

시작하려면 api를 통해 salesforce와 데이터를 동기화하는 제품이 있습니다. Google 플랫폼에서 레코드가 업데이트되면 데이터가 salesforce로 푸시되고 salesforce에서 데이터가 업데이트되면 해당 데이터가 Google 제품에 푸시됩니다. 우리가 진행하고있는 문제는 무한 루프이며 다소 번거로운 작업입니다. Salesforce에서 트리거를 실행중인 사람을 확인하여 제품에서 데이터가 업데이트되고 salesforce에 푸시 될 때 트리거가 실행되지 않도록 할 수 있습니까? 나는 이것에 대한 실행 정보를 보지 못했고 그래서 나는 그것에 대해 정말로 확신하지 못했다.Salesforce 트리거 무한 루프

감사합니다.

답변

4

Trigger.isExecuting 이외의 것이 있다고 생각하지 않습니다. Trigger.isExecuting은 이미 트리거 컨텍스트에 있는지 여부 또는 Visualforce, API 또는 익명 실행 중인지 여부를 알려줍니다.

한 가지 가능한 솔루션은 최신 업데이트의 원본을 유지하는 사용자 지정 필드를 만드는 것입니다. 그런 다음이 트리거를 사용하여 트리거 내의 논리를 올바르게 라우팅하고 마지막 업데이트가 외부 시스템에서 발생한 경우 호출하지 않아도됩니다. 또한 Trigger.old 및 trigger.new의 모든 필드를 반복하여 어떤 필드가 변경되었는지 확인할 수 있습니다.

trigger ContactDescribeExample on Contact (before update) 
{ 
     // Get describe fields to evaluate old and new triggers with 
     Map<String, Schema.SObjectField> fldObjMap = Schema.SObjectType.Contact.fields.getMap(); 
     List<Schema.SObjectField> fldObjMapValues = fldObjMap.values(); 

     // Flag to determine if field(s) other than FirstName caused this change (FirstName is just an example) 
     Boolean hasOtherChange = false; 

     // Loop through trigger batch 
     for(Contact c : Trigger.new) 
     { 
      for(Schema.SObjectField s : fldObjMapValues) 
      { 
        String fldName = s.getDescribe().getName(); 

        // Filter out fields we're not interested in 
        if(fldName != 'FirstName' && fldName != 'LastModifiedDate' && fldName != 'LastModifiedById' && fldName != 'SystemModstamp') 
        { 
         // Check to see if old and new are different 
         if(c.get(fldName) != Trigger.oldMap.get(c.Id).get(fldName)) 
           hasOtherChange = true; 
        } 
      } 
     } 
} 
+0

엄청난 도움이되었는데, 분명히이 문제를 해결할 것입니다. 신속한 회신에 감사드립니다! – jsfdev01

+0

문제는 없습니다. 기쁜 데 도움이되었습니다. – Adam

0

나는 방법에 아담과 동의 흥미로운 것은 실제로 (등 SystemTimeStamp,는 lastmodifieddate) 귀하의 기록에 변경되지 때 외부 시스템에 더 불필요한 동기화를 방지 할 수 있습니다이 방법은 여기에서이 작업을 수행하는 방법의 샘플입니다 동기화를 수행 할시기를 더 잘 식별 할 수 있습니다. UserInfo.getUserId() 메소드를 사용하여 레코드를 현재 업데이트중인 사용자를보고 사용자를 조회 할 수도 있습니다.

통합 기능을 사용하려면 사용자를 외부 제품에 할당해야한다고 생각합니다. 다행히도, 그것은 최선의 방안이 될 수있는 독특한 계정입니다. 그렇다면 현재 사용자가 누구인지를 볼 수 있으며 외부 제품인지 여부에 상관없이 다른 업데이트를 다시 보내려는 시도를 무시할 수 있습니다.

0

논리를 필터링하려는 각 "제외 소스"에 대해 Number (18,0) 유형의 대상 객체에 필드를 만듭니다. 나는 보통이 필드를 "Last Updated by [Job]"과 같이 호출합니다. 필드는 사용자가 마주하는 페이지 레이아웃에 있어서는 안됩니다.

그런 다음 면제 소스가 업데이트를 수행 할 때마다 해당 필드를 System.currentTimeMillis()로 설정합니다. 트리거는 해당 필드가 변경되었는지 확인하고, 변경된 경우 해당 소스에 대해 생략 할 로직을 면제합니다.

아담이 언급 한 해결책은 최신 업데이트 소스를 유지하는 것입니다.하지만 제대로 업데이트하지 않았거나 변경되었는지 확인하지 않으면 오류가 발생할 수 있습니다. 이것이 내가 논리 면제를 원할 때 변경되는 필드를 선호하는 이유이며, 면제 된 변경 소스에 대해서만 업데이트하면됩니다.

0

제품에서 들어오는 API 호출에 전용 사용자를 사용하는 경우 Send Outbound Messages 사용자 권한을 비활성화 할 수 있습니다. 이렇게하면 트리거 코드 중 일부가 실행되는 것을 멈추지는 않지만 개발할 때마다 업데이트주기를 막을 수 있습니다.

1

Google에서이 문제를 발견 한 사람은 트리거가 확인하는 공개 정적 변수를 설정하는 클래스를 추가하여 비슷한 문제를 해결했습니다. 기본적으로 false이고, true로 설정하면 트리거가 실행되지 않습니다.예 아래 :

public class Recursive { 
    // Static variables to avoid recursion on trigger operation 

    private static boolean working = false; 

    public static boolean isWorking() { 
     return working; 
    } 

    // Set variable to true to mark record as working 

    public static void setWorking() { 
     working = true; 
    } 

    public static void setClosed() { 
     working = false; 
    } 

} 
다음 트리거는 다음에 싸여있다

:

if (!Recursive.isWorking()) { 
    // trigger code here 
} 

정적 변수이기 때문에,이 코드 실행을 통해 설정 상태를 유지, 그래서 제일 먼저 내 정점 세트 방지하기 Recursive.setWorking();입니다 나머지 메소드 전체에서 실행을 트리거합니다.

+0

2 질문. 1 - 언제/언제 플래그를 재설정합니까? 2 - 다른 사용자가 SF UI에서 데이터를 업데이트하는 경우 어떻게해야합니까? – Moon

+0

플래그를 호출하는 클래스/트리거의 경계 내에서만 지속되므로 플래그를 아무 위치에서나 수동으로 재설정하지 않습니다. 다른 사용자가 동일한 데이터를 업데이트하는 경우 해당 트리거 인스턴스에는 고유 한 재귀 인스턴스가 있습니다. –