+ Start a Discussion
Sandhyarani S PSandhyarani S P 

Synchronize Salesforce data with an external system

Challenge Not yet complete... here's what's wrong: 
The runWarehouseEquipmentSync method does not appear to have run successfully. Could not find a successfully completed @future job for this method. Make sure that you run this method at least one before attempting this challenge. Since this method is annotated with the @future method, you may want to wait for a few seconds to ensure that it has processed successfully.

here is my code

public with sharing class WarehouseCalloutService {
    
    private static final String WAREHOUSE_URL = 'https://th-superbadge-apex.herokuapp.com/equipment';
    @future(callout=true)
    // complete this method to make the callout (using @future) to the
    // REST endpoint and update equipment on hand.
    public static void runWarehouseEquipmentSync(){
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint(WAREHOUSE_URL);
        request.setMethod('GET');
        HttpResponse response = http.send(request);
        // If the request is successful, parse the JSON response.
        String ret = '';
        if (response.getStatusCode() == 200) {
            // Deserialize the JSON string into collections of primitive data types.
            List<Object> results = (List<Object>) JSON.deserializeUntyped(response.getBody());
            
            List<Product2> LstProduct = new List<Product2>();
            for(Object obj : results)
            { 
                Map<String, Object> mapobj = (Map<String, Object>)obj;
                Product2 product = new Product2();
                           
                Integer maintenanceperiod = (Integer)mapobj.get('maintenanceperiod');               
                Integer Lifespan = (Integer)mapobj.get('lifespan');
                Integer Cost = (Integer)mapobj.get('cost');
                Boolean replacement = (Boolean)mapobj.get('replacement');
                Integer quantity = ((Integer)mapobj.get('qIntegerntity'));
                product.Name  = (String)mapobj.get('name'); 
                product.Maintenance_Cycle__c = Integer.valueof(maintenanceperiod);
                product.Cost__c = Cost;
                product.Current_Inventory__c = quantity;
                product.Lifespan_Months__c = Lifespan; 
                product.Replacement_Part__c = replacement;
                product.Warehouse_SKU__c = (String) mapobj.get('sku');
                product.ProductCode = (String)mapobj.get('_id');       
                LstProduct.add(product);
            }
            
            System.debug(LstProduct);
             upsert LstProduct Warehouse_SKU__c;
        
        }
        
       
    }
}
NagendraNagendra (Salesforce Developers) 
Hi Sandhyarani,

Sincerely regret the inconvenience for the delayed reply.

Please find the below code snippet which helps you surpass the challenge successfully.
public with sharing class WarehouseCalloutService {

    private static final String WAREHOUSE_URL = 'https://th-superbadge-apex.herokuapp.com/equipment';
    
    // complete this method to make the callout (using @future) to the
    // REST endpoint and update equipment on hand.
    @future(callout=true)
    public static void runWarehouseEquipmentSync(){
    Http http = new Http();
    HttpRequest request = new HttpRequest();
    request.setEndpoint(WAREHOUSE_URL);
    request.setMethod('GET');
    HttpResponse response = http.send(request);
    
        if(response.getStatusCode()== 200){
            
            List<Object> results = (List<Object>) JSON.deserializeUntyped(response.getBody());

            List<Product2> LstProduct = new List<Product2>();
            for(Object o : results)
            { 
                Map<String, Object> mapobj = (Map<String, Object>)o;
                Product2 product = new Product2();

                Integer maintenanceperiod = (Integer)mapobj.get('maintenanceperiod');               
                Integer Lifespan = (Integer)mapobj.get('lifespan');
                Integer Cost = (Integer)mapobj.get('cost');
                Boolean replacement = (Boolean)mapobj.get('replacement');
                Integer quantity = ((Integer)mapobj.get('qIntegerntity'));
                product.Name  = (String)mapobj.get('name'); 
                product.Maintenance_Cycle__c = Integer.valueof(maintenanceperiod);
                product.Cost__c = Cost;
                product.Current_Inventory__c = quantity;
                product.Lifespan_Months__c = Lifespan; 
                product.Replacement_Part__c = replacement;
                product.Warehouse_SKU__c = (String) mapobj.get('sku');
                product.ProductCode = (String)mapobj.get('_id');       
                LstProduct.add(product);
            }
            System.debug(LstProduct);
            upsert LstProduct;
            
            
        }
    }

}

Please mark this post as solved if it helps.

Best Regards,
Nagendra.P

 
Sandhyarani S PSandhyarani S P
Hi, This program is also not working, it's giving same error. Regards Sandhya S P
SFMiesterSFMiester
Sandhyarani, make sure you call public with sharing class WarehouseCalloutService.runWarehouseEquipmentSync() method from
DevConsole=> Execute Anonymous and then make sure that the Apex Job for your future method was created and completed before you check the challenge.
Ankit Maini.Ankit Maini.
Here is My Code: Passed
Class: WarehouseCalloutService.
public with sharing class WarehouseCalloutService {
    
    private static final String WAREHOUSE_URL = 'https://th-superbadge-apex.herokuapp.com/equipment';
    
    // complete this method to make the callout (using @future) to the
    // REST endpoint and update equipment on hand.
    @future(callout=true)
    public static void runWarehouseEquipmentSync(){
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setMethod('GET');
        request.setEndpoint(WAREHOUSE_URL);
        HttpResponse response = http.send(request);
        if(response.getStatusCode() == 200) {
            List<Object> jsonResponse = (List<Object>)JSON.deserializeUntyped(response.getBody());
            system.debug('~~ '+jsonResponse);
            List<Product2> productList = new List<Product2>();
            for(Object ob : jsonResponse) {
                Map<String,Object> mapJson = (Map<String,Object>)ob;
                Product2 pr = new Product2();
                pr.Replacement_Part__c = (Boolean)mapJson.get('replacement');
                pr.Name = (String)mapJson.get('name');
                pr.Maintenance_Cycle__c = (Integer)mapJson.get('maintenanceperiod');
                pr.Lifespan_Months__c = (Integer)mapJson.get('lifespan');
                pr.Cost__c = (Decimal) mapJson.get('lifespan');
                pr.Warehouse_SKU__c = (String)mapJson.get('sku');
                pr.Current_Inventory__c = (Double) mapJson.get('quantity');
                productList.add(pr);
            }
            
            if(productList.size()>0)
                upsert productList;
        }
        
    }
    
}

Class: WarehouseSyncSchedule
global class WarehouseSyncSchedule implements Schedulable{
    global void execute(System.SchedulableContext context){
        WarehouseCalloutService.runWarehouseEquipmentSync();
    }
}

Next You have to schedule it daily:
Run this code in Anonymous WIndow:
WarehouseSyncSchedule reminder = new WarehouseSyncSchedule();
// Seconds Minutes Hours Day_of_month Month Day_of_week optional_year
String sch = '0 0 8 * * ? *';

String jobID = System.schedule('WarehouseSyncSchedule', sch, reminder);

 
Rajani KalleRajani Kalle
Hi Ankit , I have tried  above code to solve Challenge 2  of Apex Specialist, but its not working for me:
Challenge Not yet complete... here's what's wrong: 
The runWarehouseEquipmentSync method does not appear to have run successfully. Could not find a successfully completed @future job for this method. Make sure that you run this method at least one before attempting this challenge. Since this method is annotated with the @future method, you may want to wait for a few seconds to ensure that it has processed successfully.
JAGDISH MOREJAGDISH MORE
Go to remote sites from setup and then add the Endpoint to as the given URL in the Challange. Then surely you will pass the challange.
Divya Jain 32Divya Jain 32
Hi Jagdish,

I have gone through the above code and added URL to the remote site settings, but getting the error.

Challenge Not yet complete... here's what's wrong: 
The runWarehouseEquipmentSync method does not appear to have run successfully. Could not find a successfully completed @future job for this method. Make sure that you run this method at least one before attempting this challenge. Since this method is annotated with the @future method, you may want to wait for a few seconds to ensure that it has processed successfully.
Watson Marconato 8Watson Marconato 8
Please, check your Remote Site Settings. You should add URL.

Setup > Remote Site Settings
AnantGargAnantGarg
Your code seems ok. There are two steps you might be missing:
  1. Add your WAREHOUSE_URL into the remote site settings from setup>Remote Site Settings>New Remote Site, fill 'https://th-superbadge-apex.herokuapp.com/equipment' in Remote Site URL and any name in Remote Site Name
  2. Open Execute Anonymous Window in the developer console and paste 
    WarehouseCalloutService.runWarehouseEquipmentSync();

    and click 'Execute' then check your challenge 
Sudhir PandaSudhir Panda
Yup, the things which @AnantGarg said is absolutely correct, as we need to run the following code only:- 
WarehouseCalloutService.runWarehouseEquipmentSync();
The above examples in which we see String sch = '0 0 8 * * ? *'; is a cron expression, its correct but to complete our challenge its not as it schedules the job into future time and we would need to wait.
Keep it simple 1. Add the url in the remote site settings with any name and run the above one liner code in the anonymous window.
Nidhi Sharma 158Nidhi Sharma 158
public with sharing class WarehouseCalloutService {

    private static final String WAREHOUSE_URL = 'https://th-superbadge-apex.herokuapp.com/equipment';
    // Please note to add the Endpoint URL in Remote Site Settings.
    @future(callout=true)
    public static void runWarehouseEquipmentSync() {
        // create new http request
        Http http = new Http();
        
        HttpRequest req = new HttpRequest();
        req.setEndpoint(WAREHOUSE_URL); //Setting Endpoint URL for the request.
        req.setMethod('GET');
        HttpResponse res = http.send(req);
        List<product2> equipmentList = new List<product2>();
        if(res.getStatusCode()==200){
            //Deserialize the JSON String
           List< Object> result =(List<object>)JSON.deserializeUntyped(res.getBody());    
            
            // For each equipment we create a new product with all the new feild values.
           for(Object productMap: result){
               Map<String,Object> prod = (Map<String,Object>)productMap;
                Product2 newprod = new Product2();
                newprod.ExternalId=(String)prod.get('_id');
                newprod.Replacement_Part__c=true;
                newprod.Cost__c=(Decimal)prod.get('cost');
                newprod.Current_Inventory__c=(Decimal)prod.get('quantity');
                newprod.Lifespan_Months__c=(Double)prod.get('lifespan');
                newprod.Name=(String)prod.get('name');
                newprod.Maintenance_Cycle__c=(Integer)prod.get('maintenanceperiod');
                newprod.ExternalId=(String)prod.get('sku');
                equipmentList.add(newprod);
            }
            // we upsert the product to the database when the equipment list is greater than zero.
            if(equipmentList.size()>0){
                upsert equipmentList;}
        }  
    }
}
 
Sourav Thapliyal 9Sourav Thapliyal 9

Hi, if anyone is yet having trouble use the below code. Tested and verified.

public with sharing class WarehouseCalloutService {
    
    private static final String WAREHOUSE_URL = 'https://th-superbadge-apex.herokuapp.com/equipment';
    
    @future(callout=true)
    public static void runWarehouseEquipmentSync() {
        //ToDo: complete this method to make the callout (using @future) to the
        //      REST endpoint and update equipment on hand.
        List<Product2> prods2Update = new List<Product2>();
        HttpRequest req = new HttpRequest();
        req.setEndpoint(WAREHOUSE_URL);
        req.setMethod('GET');
        req.setHeader('Content-Type', 'application/json;charset=UTF-8');
        
        http http = new http();
        HttpResponse res = new HttpResponse();
        res = http.send(req);
        if(res.getStatusCode() == 200)
        {
            string respStr = res.getBody().replace('replacement','Replacement_Part__c').replace('maintenanceperiod','Maintenance_Cycle__c');
            respStr = respStr.replace('Cost','Cost__c').replace('lifespan','Lifespan_Months__c');
            respStr = respStr.replace('sku','Warehouse_SKU__c').replace('quantity','Current_Inventory__c');
            List<Product2> results = (List<Product2>) JSON.deserialize(respStr, List<Product2>.class);
            system.debug('response key set---> '+results);
            for(Product2 item : results)
            {
                //system.debug('id---> '+ item.Current_Inventory__c);
                prods2Update.add(item);
            }
        }
        else
        {
            system.debug('error code '+res.getStatusCode()+'error status '+res.getStatus());
        }
        
        if(!prods2Update.isEmpty())
        {
            upsert prods2Update Warehouse_SKU__c;
            system.debug('list got updated. Size: '+prods2Update.size());
        }
        else
            system.debug('List is empty.Size: '+prods2Update.size());
        
    }
}

 

If worked for you mark it the best answer.

Parag DevghareParag Devghare
Hi There, In addition to the above solution.

Implement Queable interface for class 'WarehouseCalloutService'.

This could have not been the issue for others as mentioned above if you have tried executing your method once in Anonymous window. User-added image
 
Rajat SonkusareRajat Sonkusare
Thanks @Parag Devghare, Solution worked for me.
RAVINDERREDDY KAMBALAPALLYRAVINDERREDDY KAMBALAPALLY
Implementing Queueable in class and execute Queuebale context in method worked for me.
RAVINDERREDDY KAMBALAPALLYRAVINDERREDDY KAMBALAPALLY

What Parag Devghare said is correct.
Prashant RupnurPrashant Rupnur
Please try below code:
public with sharing class WarehouseCalloutService implements Queueable, Database.AllowsCallouts{

    private static final String WAREHOUSE_URL = 'https://th-superbadge-apex.herokuapp.com/equipment';
   
    public void execute(QueueableContext context){
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint(WAREHOUSE_URL);
        request.setMethod('GET');
        HttpResponse response = http.send(request);
        if(response.getStatusCode() == 200)
        {
            List<Object> externalProducts = (List<Object>) JSON.deserializeUntyped(response.getBody());
            List<Product2> newProducts = new List<Product2>();
            
            for(Object p : externalProducts)
            {
                Map<String, Object> productMap = (Map<String, Object>) p;
                Product2 pr = new Product2();
                pr.Replacement_Part__c = (Boolean)productMap.get('replacement');
                pr.Cost__c = (Integer)productMap.get('cost');
                pr.Current_Inventory__c = (Integer)productMap.get('quantity');
                pr.Lifespan_Months__c = (Integer)productMap.get('lifespan') ;
                pr.Maintenance_Cycle__c = (Integer)productMap.get('maintenanceperiod');
                pr.Warehouse_SKU__c = (String)productMap.get('sku');
                pr.ProductCode = (String)productMap.get('_id');
                pr.Name = (String)productMap.get('name');
                newProducts.add(pr);
            }
            if(newProducts.size() >0)
            {
                upsert newProducts; 
            }
        }   
    }
}
DHIRAJ SABALEDHIRAJ SABALE
public with sharing class WarehouseCalloutService implements Queueable, Database.AllowsCallouts {  
   private static final String WAREHOUSE_URL = 'https://th-superbadge-apex.herokuapp.com/equipment';    
   public static void runWarehouseEquipmentSync(){
       Http http = new Http();
       HttpRequest request = new HttpRequest();
       request.setMethod('GET');
       request.setEndpoint(WAREHOUSE_URL);
       HttpResponse response = http.send(request);
       if(response.getStatusCode() == 200) {
           List<Object> jsonResponse = (List<Object>)JSON.deserializeUntyped(response.getBody());
           system.debug('~~ '+jsonResponse);
           List<Product2> productList = new List<Product2>();
           for(Object ob : jsonResponse) {
               Map<String,Object> mapJson = (Map<String,Object>)ob;
               Product2 pr = new Product2();
               pr.Replacement_Part__c = (Boolean)mapJson.get('replacement');
               pr.Name = (String)mapJson.get('name');
               pr.Maintenance_Cycle__c = (Integer)mapJson.get('maintenanceperiod');
               pr.Lifespan_Months__c = (Integer)mapJson.get('lifespan');
               pr.Cost__c = (Decimal) mapJson.get('lifespan');
               pr.Warehouse_SKU__c = (String)mapJson.get('sku');
               pr.Current_Inventory__c = (Double) mapJson.get('quantity');
               productList.add(pr);
           }            
           if(productList.size()>0)
               upsert productList;
       }        
   }    
   public static void execute(QueueableContext context){
       runWarehouseEquipmentSync();
   }
}





In Execute Anonymous Window, use enqueueJob.

System.enqueueJob(New WarehouseCalloutService());
Veera Lakshmi VaidadiVeera Lakshmi Vaidadi

@DHIRAJ SABALE.......his code works for me thanks a lot yaar
William Wang 26William Wang 26
Actually, we needn't implements DataBase.AllowsCallouts...

---------------------
public with sharing class WarehouseCalloutService implements Queueable {

    private static final String WAREHOUSE_URL = 'https://th-superbadge-apex.herokuapp.com/equipment';
    
    @future(callout=true)
    public static void runWarehouseCalloutSync(){
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setMethod('GET');
        request.setEndpoint(WAREHOUSE_URL);
        HttpResponse response = http.send(request);
        if(response.getStatusCode() == 200){
            List<Object> jsonResponse = (List<Object>)JSON.deserializeUntyped(response.getBody());
            if(jsonResponse.size() > 0){
               List<Product2> products = new List<Product2>();
                for(Object o : jsonResponse){
                    Product2 pr = new Product2();
                    Map<String,Object> pro = (Map<String,Object>)o;
                    pr.Replacement_Part__c = (Boolean)pro.get('replacement');
                    pr.Cost__c = (Integer)pro.get('cost');
                    pr.Current_Inventory__c = (Integer)pro.get('quantity');
                    pr.Lifespan_Months__c = (Integer)pro.get('lifespan');
                    pr.Maintenance_Cycle__c = (Integer)pro.get('maintenanceperiod');
                    pr.Warehouse_SKU__c = (String)pro.get('sku');
                    pr.ProductCode = (String)pro.get('_id');
                    pr.Name = (String)pro.get('name');
                    products.add(pr);
                }
                if(products.size() > 0){
                    System.debug(products);
                    upsert products;
                }
            }
        }
    }
    
    public static void execute(QueueableContext context){
        runWarehouseCalloutSync();
    }
}
-------------------
this code is works.