function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Daniel B ProbertDaniel B Probert 

Another parsing XML Query

Hi,

 

I'm doing a HTTP Callout from a trigger on a specific object. The trigger basically runs when a record is updated and checks online for related records.

 

I thought I had worked it out but I'm getting an error of:

 

System.ListException: Before Insert or Upsert list must not have two identically equal elements

here is my code basically it should go off to an external site - then grab the xml response - then go through an create a new record for each child element based on my if statements and also fill in the a lookup field with the record id the the trigger was initiated from.

 

i think it's because of how i'm grabbing the recordid and formid at the beginning but am not sure.

 

public class MonitoringQuestionsUpdater {
  @Future(callout=true)
  public static void updateMQ() {
    List<Monitoring_Form__c> mfcs = [SELECT Id, Form_Id__c FROM Monitoring_Form__c]; 
    for(Monitoring_Form__c a:mfcs){
    string formid = a.form_id__c;
    string recordid = a.id;
    Http http = new Http();
    HttpRequest req = new HttpRequest();
    req.setEndpoint('https://magpi.com/api/questions?username=myusername&accesstoken=mytoken&surveyid='+formid);
    req.setMethod('POST'); 
    HTTPResponse res = http.send(req);
    System.debug(res.getBody());
    List<Monitoring_Questions__c> newquestions = new List<Monitoring_Questions__c>();
    set<string> existingmQuestSetId = new set<string>();
 //iterate thru the existing mforms and add allthe form_id__c in a set. And then use this set to later check for duplicates
 for(monitoring_questions__c mquest: [SELECT Id, questionid__c FROM Monitoring_Questions__c]){
    existingmQuestSetId.add(mquest.questionid__c);
 }
    string s = res.getBody();
    Dom.Document docx = new Dom.Document();
        docx.load(s);
        dom.XmlNode xroot = docx.getrootelement();
        dom.XmlNode [] xrec = xroot.getchildelements(); //Get all Record Elements
        for(Dom.XMLNode child : xrec)
            {
        for(dom.XmlNode magpi : child.getchildren() ) {
           Monitoring_Questions__c mq = new Monitoring_Questions__c();
           if (magpi.getname() == 'Id') {
           System.debug(magpi.getname() == 'Id');
                   mq.QuestionID__c = magpi.gettext();
             }
           if (magpi.getname() == 'Prompt') {
           System.debug(magpi.getname() == 'Prompt');
                   mq.Question_Prompt__c = magpi.gettext();
             }
           if (magpi.getname() == 'Name'){
           System.debug(magpi.getname() == 'Name');
                  mq.Question_Name__c = magpi.gettext();  
         }
         mq.monitoring_form__c = recordid;
        if(!existingmQuestSetId.contains(mq.questionid__c)){
            Newquestions.add(mq);
                }
            }
        }
        insert newquestions;
      }
    }
}

 

any help is appreciated.

 

dan

 

Best Answer chosen by Admin (Salesforce Developers) 
Prashant TiwariPrashant Tiwari

Try to initialize the list "Newquestions" inside the "  for loop " and see if it works.

 

 

Thanks,

 

Prashant Tiwari

 

mark it as solved if the solution worked as it might help others

All Answers

Saikishore Reddy AengareddySaikishore Reddy Aengareddy

change 

 

if(!existingmQuestSetId.contains(mq.questionid__c)){

to

if(!existingmQuestSetId.containsIgnoreCase(mq.questionid__c)){

 


and see if it helps.. because abc and ABC are treated as different values.. 

Prashant TiwariPrashant Tiwari

Try to initialize the list "Newquestions" inside the "  for loop " and see if it works.

 

 

Thanks,

 

Prashant Tiwari

 

mark it as solved if the solution worked as it might help others

This was selected as the best answer
Daniel B ProbertDaniel B Probert
hey that seems to have done the trick although now rather than it creating one record it is creating 3 per question.

i.e once with the questionid, one with the question name and then one with the prompt.

ideally this should be one single record that is being created, is this a loop thing again?

cheers for your help.
Daniel B ProbertDaniel B Probert
scrap that figured out my ordering was wrong in the apex. cheers for you help though.
Daniel B ProbertDaniel B Probert

i have this running from a trigger after update - how do i can the record from the trigger into my apex class - i thought that part would be simple but cna't figure it out.

 

trigger=

trigger MonitoringFormQuestions on Monitoring_Form__c (after insert, after update) {
  
  Monitoring_Form__c[] mformupdate = Trigger.New;

    MonitoringQuestionsUpdater.updateMQ();

}

 at the top of my class i have:

 

public class MonitoringQuestionsUpdater {
  @Future(callout=true)
  public static void updateMQ() {
    List<Monitoring_Form__c> mfcs = [SELECT Id, Form_Id__c FROM Monitoring_Form__c]; 
    for(Monitoring_Form__c a:mfcs){
    string formid = a.form_id__c;

 how can i include a where id =: trigger record id

 

i was looking at the trigger map key but couldn't get that working so thought maybe i just need a different approach?

Daniel B ProbertDaniel B Probert
no worries i've figured this out and it's working exactly as i want it to - thanks for your help.
Prashant TiwariPrashant Tiwari
That's Great..!! Did you pass the set of IDs from trigger to the Future method..
Daniel B ProbertDaniel B Probert

yes so my trigger ended up looking like this:

 

trigger MonitoringFormQuestions on Monitoring_Form__c (after update) {
  Set<string> mformupdate = new Set<string> ();
  for (Monitoring_Form__c osg : [Select Id from Monitoring_Form__c where id in :Trigger.newMap.keyset()]) { 
   mformupdate.add(osg.id);      
}
    MonitoringQuestionsUpdater.updateMQ(mformupdate);
}

 and then i updated my future class to this:

 

public class MonitoringQuestionsUpdater {
  @Future(callout=true)
  public static void updateMQ(set<string> mformupdate) {
    List<Monitoring_Form__c> mfcs = [SELECT Id, Form_Id__c FROM Monitoring_Form__c where id in: mformupdate]; 
    for(Monitoring_Form__c a:mfcs){
    string formid = a.form_id__c;

 so now when ever i update a form it will check to see if all the questions are in salesforce :)

 

cheers for your assistance i got there in the end.