+ Start a Discussion
Rebecca Hendricks 23Rebecca Hendricks 23 

Apex Specialist Superbadge - Step 2 Unable to run successfully

I'm trying to complete the Apex Specialist Superbadge.  I have created my WarehouseCalloutService apex class and it seems to match how others have created their class.  However when I run my code and then try and check the challenge, I'm getting the error that seems many others are getting about the Challenge Not Yet Complete.... "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 endpoint = 'https://th-superbadge-apex.herokuapp.com/equipment';

    @future(callout = true)	//need this so that it knows to call to external source
    public static void runWarehouseEquipmentSync(){
        Http http = new Http();
        HttpRequest httpRequest = new HttpRequest();
        httpRequest.setEndpoint(endpoint);
        httpRequest.setMethod('GET');
        HttpResponse httpResponse = http.send(httpRequest);
        
        //if successfully get the JSON file, need to parse out to different equipment objects
        if (httpResponse.getStatusCode() == 200){ //status = "OK" (this is for GET or HEAD requests)
            List<Object> equipmentList = (List<Object>) JSON.deserializeUntyped(httpResponse.getBody());
            List<Product2> products = new List<Product2>();
            
            for(Object item: equipmentList){
                Map<String, Object> productMap = (Map<String,Object>) item;	//map of item(s) in JSON file
                Product2 product = new Product2();	//list of products to insert/update in system
                
                product.Replacement_Part__c = (Boolean) productMap.get('replacement');
                product.Cost__c = (Integer) productMap.get('cost');                
                product.Current_Inventory__c = (Integer) productMap.get('quantity');
                product.Lifespan_Months__c = (Integer) productMap.get('lifespan');
                product.Maintenance_Cycle__c = (Integer) productMap.get('maintenanceperiod');
                product.Warehouse_SKU__c = (String) productMap.get('sku');
                product.Name = (String) productMap.get('name');
                product.ProductCode = (String) productMap.get('_id');
                products.add(product);
            }
            
            if(products.size() > 0){	//only need to upsert if items actually exist
                System.debug(products);
                upsert products;
            }
        }
    }
}

According to some other strings I have found on this error (https://developer.salesforce.com/forums/?id=906F0000000kE7DIAU), this is what I've looked at and the current status of it:
  • Field Level Security for Lifespan_Months__c field on Equipment (Product2) object: Visible for All profiles
  • User-added image
  • Remote Site Settings: Added this URL as a Remote Site and confirmed it is active - https://th-superbadge-apex.herokuapp.com
  • User-added image
  • Apex Jobs: Confirmed it is listed in Apex Jobs log and that it's listing as a "Future" job type and a "Completed" status.
  • User-added image
  • Execution Log: Confirmed that it shows that 1 of 50 Future classes were executed.
  • User-added image
  • SOQL Query: Confirmed that the job was placed into the system.
  • User-added image

Any assistance as to why I am not getting a complete on this task would be much appreciated!
SandhyaSandhya (Salesforce Developers) 
Hi,

Refer below link that may help you.

https://salesforce.stackexchange.com/questions/134346/could-not-find-a-successfully-completed-future-job
 
Please mark it as solved if my reply was helpful. It will make it available for other as the proper solution.
 
Best Regards
Sandhya
 
Rebecca Hendricks 9Rebecca Hendricks 9
@Sandhya

As I mentioned, I have already ran the SOQL query as the link suggests and confirmed that the Apex job has been ran and completed.  I also did as the second comment had suggested and ensured that my endpoint had been added to the Remote Site Settings.
Christopher Thaxter 4Christopher Thaxter 4
For those who are looking - I had the same problems as above. I was able to solve it by selecting the proper Trailhead Playground on the challenge page! I had two playgrounds, but wasn't used to having two, and the one I was using was not my default. Sometimes the answer is somewhere completely separate from where you're looking!
Swapnil GuravSwapnil Gurav
I was also facing same problem. I added the Endpoint URL at Setup->Security->Remote site settings. Then I executed WarehouseCalloutService.runWarehouseEquipmentSync(); from Execute Anonymous Window. I ran query below query after this which was showing Status as Completed.
SELECT Id, JobType, MethodName, Status FROM AsyncApexJob WHERE CompletedDate = TODAY
Once it shows Completed in Query result, click on Check Challenge in Trailhead. It will complete without any issue.
Monika MekalaMonika Mekala
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.
    
		
		HttpResponse response = getResponse(); 
        if(response.getStatusCode() == 200)
        {
            List<Product2> results = getProductList(response); //get list of products from Http callout response
            
            if(results.size() >0)
            upsert results Warehouse_SKU__c; //Upsert the products in your org based on the external ID SKU
        }
        
    }
        //Get the product list from the external link
        public static List<Product2> getProductList(HttpResponse response)
        {
            
            List<Object> externalProducts = (List<Object>) JSON.deserializeUntyped(response.getBody()); //desrialize the json response
            List<Product2> newProducts = new List<Product2>();
            
            for(Object p : externalProducts)
            {
                Map<String, Object> productMap = (Map<String, Object>) p;
                Product2 pr = new Product2();
            	//Map the fields in the response to the appropriate fields in the Equipment object
                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);
            }
            
            return newProducts;
            
        }
        
        // Send Http GET request and receive Http response
    
    public static HttpResponse getResponse() {
        
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint(WAREHOUSE_URL);
        request.setMethod('GET');
        HttpResponse response = http.send(request);
        
        return response;
        
    }
    }

I was able to complete the challenge successfully.  This was the code I wrote.  Pelase make sure you Run this atleast once in the Execute anonymous window before checking the challenge. : WarehouseCalloutService.runWarehouseEquipmentSync(); 
Brendon Wilkinson 73Brendon Wilkinson 73
Hi Rebecca,

Probably too late but for anyone else who sees this. The issue was that you were performing an upsert without specifying the correct external id field: 
upsert products Warehouse_SKU__c;
 
Best,
Brendon
Rutu PatelRutu Patel

Hi,

I have done challenge 2 

First create In Quick Box -> Setting -> Remote Site  -> New
Remote Site Name : th_superbadge
Remote Site URL : https://th-superbadge-apex.herokuapp.com

Then open Developer Console and write code In WarehouseCalloutService .apxc:

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.
    
        
        HttpResponse response = getResponse(); 
        if(response.getStatusCode() == 200)
        {
            List<Product2> results = getProductList(response); //get list of products from Http callout response
            
            if(results.size() >0)
            upsert results Warehouse_SKU__c; //Upsert the products in your org based on the external ID SKU
        }
        
    }
        //Get the product list from the external link
        public static List<Product2> getProductList(HttpResponse response)
        {
            
            List<Object> externalProducts = (List<Object>) JSON.deserializeUntyped(response.getBody()); //desrialize the json response
            List<Product2> newProducts = new List<Product2>();
            
            for(Object p : externalProducts)
            {
                Map<String, Object> productMap = (Map<String, Object>) p;
                Product2 pr = new Product2();
                //Map the fields in the response to the appropriate fields in the Equipment object
                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);
            }
            
            return newProducts;
            
        }
        
        // Send Http GET request and receive Http response
    
    public static HttpResponse getResponse() {
        
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint(WAREHOUSE_URL);
        request.setMethod('GET');
        HttpResponse response = http.send(request);
        
        return response;
        
    }
    }

And open anonymous window and write code:

WarehouseCalloutService.runWarehouseEquipmentSync();

Then execute once before check challenge.I have do it and it work currectly. 

Thanks.

Aliaksandr KotAliaksandr Kot
hi!
add site in remote
Setup > Quick search > Remote Site Settings > New Remote Site :
Remote Site Name: th_superbadge
Remote Site URLhttps: //th-superbadge-apex.herokuapp.com