+ Start a Discussion
Abhiram Sheshadri 9Abhiram Sheshadri 9 
Hi,

I have written the below classes as part of the trailhead challenge for Apex REST callouts.

The class -

public class AnimalLocator {
  
  public static String getAnimalNameById(Integer id) {
    
    Http http = new Http();
    HttpRequest request = new HttpRequest();
    request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals/'+id);
    request.setMethod('GET');
    
    HttpResponse response = http.send(request);
    List<Object> animals; 
    String returnValue; 
    
    // parse the JSON response
    if (response.getStatusCode() == 200) {
      Map<String, Object> result = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
      animals = (List<Object>) result.get('animals');
      System.debug(animals);
    }
    
    if (animals.size() > 0 && animals != NULL && id < animals.size()) {
      returnValue = (String) animals.get(id);
    }
    
    return returnValue;
  } 
    
}

Mock Response Class - 

@isTest
global class AnimalLocatorMock implements HttpCalloutMock {
     // Implement this interface method
    global HTTPResponse respond(HTTPRequest request) {
        // Create a fake response
        HttpResponse response = new HttpResponse();
        response.setHeader('Content-Type', 'application/json');
        response.setBody('{"animals": ["majestic badger", "fluffy bunny", "scary bear", "chicken", "mighty moose"]}');
        response.setStatusCode(200);
        return response; 
    }
}

Test Class - 

@isTest
private class AnimalLocatorTest{
    @isTest static void AnimalLocatorMock1() {
        Test.setMock(HttpCalloutMock.class, new AnimalLocatorMock());
        string result = AnimalLocator.getAnimalNameById(3);
        String expectedResult = 'chicken';
        System.assertEquals(result,expectedResult );
    }
}

I have got 100% code coverage for the main class. But when I check the challenge I get 

Challenge Not yet complete... here's what's wrong: 
There was an unexpected error in your org which is preventing this assessment check from completing: System.NullPointerException: Attempt to de-reference a null object

Please tell me if any changes to the code is required. It's really frustrating as I am stuck from past 3-4 days with this unit.

Thanks & Regards,

Abhiram Sheshadri
Best Answer chosen by Abhiram Sheshadri 9
Uvais KomathUvais Komath
public class AnimalLocator{
    public static String getAnimalNameById(Integer x){
        Http http = new Http();
        HttpRequest req = new HttpRequest();
        req.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals/' + x);
        req.setMethod('GET');
        
        HttpResponse res = http.send(req);
            if (response.getStatusCode() == 200) {
        Map<String, Object> results = (Map<String, Object>)JSON.deserializeUntyped(res.getBody());
        Map<String, Object> animal = (Map<String, Object>) results.get('animal');
        return (String)animal.get('name');

}
    }
}
works fine for me
 
supriya Goresupriya Gore 
component:
<aura:component implements="force:appHostable" controller="FetchRegistrations" >
    <aura:attribute name="reg" type="Registration__c[]"/>
    <ui:button label="Get Registrations" press="{!c.myAction}"/>
    <aura:iteration var="r" items="{!v.reg}" >
    <p>{!r.name}</p>
    </aura:iteration>
</aura:component>


Controller:
({
   myAction : function(component, event, helper) {
        var action = component.get("c.getAllregistrations");
        action.setCallback(this, function(response){
            var name = response.getState();
            if (name === "SUCCESS") {
                component.set("v.reg", response.getReturnValue());
            }
        });
     $A.enqueueAction(action);
    }
})

Apex:
global with sharing class FetchRegistrations {
@auraEnabled
    public static List<Registration__c> getAllregistrations()
    {
     List<Registration__c> reg=new LIST<Registration__c>();  
        reg=[select id,name,Email__c from Registration__c];
        return reg;
    } 
    public Registration__c getSelectedregistrations(Id id)
    {    
      Registration__c  reg=[select id,name,Email__c from Registration__c where id=:id];
        return reg;
    } 
   
}
Best Answer chosen by supriya Gore
Prajyot KerkarPrajyot Kerkar
Change {!r.name} to {!r.Name} as javascript is case-sensitive name & Name are different
simon chaosimon chao 
Hi, I currently have the code below
<td data-label="TESTING"><lightning:input type="number" min="0" label="" name=" " value="{!v.testint.test__c}"/></td>
I don't want any decimals, so if there is a decial a error will show up, as seen in the pic below 
User-added image
I also have a Next button at the bottom of the page. Is it possible to make the page stay on the current page when a error such as the above shows up? And only allow the page to go to the next section when the number have been changed from a decimal to a whole number, or when there are no errors shown. 
 
Best Answer chosen by simon chao
simon chaosimon chao
i added in a if function for the function that dictates the page redirect, and it works. [solved] 
simon chaosimon chao 
How can i round or truncate off the decimal? I don't want the decimal to show. If a user input 1.5 I want it to show either 2 or 1 so either round up or truncate off the decimal, either one works. 

Right now I have:
<lightning:input type="number"  value="{!v.customNumber__c}"/>

Any help is greatly appreciated, thank you.
 
Best Answer chosen by simon chao
simon chaosimon chao
i ended up using ui:input instead of lightning:input. thanks everyone for your help 
ayisha aroraayisha arora 
Create a new link on the contact row to delete the contact from the account. On clicking the link, the contact should be deleted this time using VisualForce Remoting. On successful deletion, an alert should be displayed on the page stating “The contact has been deleted”.
Best Answer chosen by ayisha arora
Nitin ShyamnaniNitin Shyamnani
Hi Ayisha,

You need to create an Apex class and add this method:

@RemoteAction
global static Boolean updateContact(String conId) {
        try{
             contact con = new contact(AccountID = null, ID = conId);
              update con;          
              return true;
        }
        catch(Exception){
              return false;
         }
}

You can call this method using "Visualforce.remoting.Manager.invokeAction" and pass the contact ID to remove the accountId, and you will get result true if successfully deleted or false in case of any issue.

Here is the link for example of VF Remoting: https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_js_remoting_example.htm

Thanks,
Nitin
Michal KozakMichal Kozak 
Hi, I tried to report this bug to salesforce, but was redirected here.
This is very likely internal salesforce issue.
When you try to do any operation with integer received from lightning component (@AuraEnabled), you got 
FATAL_ERROR|Internal Salesforce.com Error
 
public with sharing class TestController2 {
    @AuraEnabled
    public static integer getTestResult(integer pageNumber) {
        return pageNumber + 1;
    }
}


Full log included:
34.0 APEX_CODE,DEBUG;APEX_PROFILING,INFO;CALLOUT,INFO;DB,INFO;SYSTEM,DEBUG;VALIDATION,INFO;VISUALFORCE,INFO;WORKFLOW,INFO
23:30:39.143 (143052245)|EXECUTION_STARTED
23:30:39.143 (143081946)|CODE_UNIT_STARTED|[EXTERNAL]|01pU0000001YzfB|TestController2.getTestResult
23:30:39.143 (143501666)|METHOD_ENTRY|[1]|01pU0000001YzfB|TestController2.TestController2()
23:30:39.143 (143599706)|SYSTEM_MODE_ENTER|false
23:30:39.143 (143634027)|SYSTEM_MODE_EXIT|false
23:30:39.143 (143644512)|METHOD_EXIT|[1]|TestController2
23:30:39.144 (144047168)|FATAL_ERROR|Internal Salesforce.com Error
23:30:39.144 (144066440)|CUMULATIVE_LIMIT_USAGE
23:30:39.144 (144066440)|LIMIT_USAGE_FOR_NS|(default)|
  Number of SOQL queries: 0 out of 100
  Number of query rows: 0 out of 50000
  Number of SOSL queries: 0 out of 20
  Number of DML statements: 0 out of 150
  Number of DML rows: 0 out of 10000
  Maximum CPU time: 0 out of 10000
  Maximum heap size: 0 out of 6000000
  Number of callouts: 0 out of 100
  Number of Email Invocations: 0 out of 10
  Number of future calls: 0 out of 50
  Number of queueable jobs added to the queue: 0 out of 50
  Number of Mobile Apex push calls: 0 out of 10

23:30:39.144 (144066440)|LIMIT_USAGE_FOR_NS|Vendavo|
  Number of SOQL queries: 0 out of 100
  Number of query rows: 0 out of 50000
  Number of SOSL queries: 0 out of 20
  Number of DML statements: 0 out of 150
  Number of DML rows: 0 out of 10000
  Maximum CPU time: 0 out of 10000
  Maximum heap size: 0 out of 6000000
  Number of callouts: 0 out of 100
  Number of Email Invocations: 0 out of 10
  Number of future calls: 0 out of 50
  Number of queueable jobs added to the queue: 0 out of 50
  Number of Mobile Apex push calls: 0 out of 10

23:30:39.144 (144066440)|CUMULATIVE_LIMIT_USAGE_END

23:30:39.144 (144134140)|CODE_UNIT_FINISHED|TestController2.getTestResult
23:30:39.147 (147174875)|EXECUTION_FINISHED

Note that system.debug('pageNumber: ' + pageNumber); works. But all other integer operations fail.
Please advise how to circumvent this issue.
Best Answer chosen by Michal Kozak
Michal KozakMichal Kozak
Workaround, that works:
public static integer getTestResult(string pageNumber) {
        integer tmp = integer.valueof(pageNumber);
        return tmp + 1;
    }

change the parameter to string and convert its value in the code.
Stavros McGillicuddyStavros McGillicuddy 
I am trying to update the Sample_QB_Error__c field with Hello
This code throws "an Invalid or unexpected token"  

Thanks
{!REQUIRESCRIPT("/soap/ajax/32.0/connection.js")} 
{!REQUIRESCRIPT("/soap/ajax/32.0/apex.js")} 
var record = new sforce.SObject("Opportunity"); 
record.Id = ‘{!Opportunity.Id}’; 
record.Sample_QB_Error__c ="Hello"; 
sforce.connection.update([record]); 
window.location.reload();

 
Best Answer chosen by Stavros McGillicuddy
@Karanraj@Karanraj
It's just problem with the single quotation mark in the code.
Try the below updated code
{!REQUIRESCRIPT("/soap/ajax/32.0/connection.js")}
{!REQUIRESCRIPT("/soap/ajax/32.0/apex.js")}
var record = new sforce.SObject("Opportunity");
record.Id = '{!Opportunity.Id}';
record.Sample_QB_Error__c ="Hello";
sforce.connection.update([record]);
window.location.reload();

 
hanifa fatimahanifa fatima 
trigger CreationOfContact on Account (after insert,after Update) {
Map<Id,Decimal> mp=new Map<Id,Decimal>();
list<Contact> lst=new List<Contact>();
  for(Account a:Trigger.New)
  { 
   mp.put(a.id,a.Number_Of_Contacts__c);
  }
   if(Trigger.isInsert && Trigger.isAfter)
   {
    if(mp.size()>0 && mp!=null)
    {
     for(Id a:mp.keyset())
     {
      for(Integer i=1;i<=mp.get(a);i++)
      {
        Contact c=new Contact();
        c.lastname='Test'+i;
        c.accountid=a;
        lst.add(c);
      }
     }
    }
   }
   insert lst;
   if(Trigger.isUpdate && Trigger.isAfter)
   {
    
   for(Account a:Trigger.new)
   {
    Decimal a1=trigger.oldmap.get(a.id).Number_Of_Contacts__c;
    Decimal a2=trigger.newMap.get(a.id).Number_Of_Contacts__c;
    Decimal a3=0;
    if(a2>a1)
    {
      a3=a2-a1;
      for(Integer i=1;i<=a3;i++)
      {
        Contact c=new Contact();
        c.lastname='Update' +i;
        c.AccountId=a.id;
        lst.add(c);
      }
     }    
    }
      insert lst;
   }
   
}


In this trigger i have created a custom field called no.of.contacts on account object, i've the following scenario:
1. When a new account is created and the that field is populated with (say 2) it should create 2 new contacts.

2. When i edit the that field ( say to 5 now before it was 2 ) so the difference of both is now 3, so it should 3 more contacts.

3. when i edit that field to (say to 4 now earlier the new updated value is 5) so the difference is 1 here , therefore 1contact should be deleted.


So, the code i've written works well upto 2nd scenario, the only problem i;m facing now is at 3rd scenario.

Could someone help me out?

Best Answer chosen by hanifa fatima
Steven NsubugaSteven Nsubuga
Try this Hanifa.
trigger CreationOfContact on Account (after insert,after Update) {
Map<Id,Decimal> mp=new Map<Id,Decimal>();
Map<Id,Decimal> mp2=new Map<Id,Decimal>();
list<Contact> lst=new List<Contact>();
list<Contact> toAdd=new List<Contact>();
list<Contact> toDelete=new List<Contact>();

  for(Account a:Trigger.New)
  { 
   mp.put(a.id,a.Number_Of_Contacts__c);
  }
   if(Trigger.isInsert && Trigger.isAfter)
   {
    if(mp.size()>0 && mp!=null)
    {
     for(Id a:mp.keyset())
     {
      for(Integer i=1;i<=mp.get(a);i++)
      {
        Contact c=new Contact();
        c.lastname='Test'+i;
        c.accountid=a;
        lst.add(c);
      }
     }
    }
   }
   insert lst;
   if(Trigger.isUpdate && Trigger.isAfter)
   {
    list<Contact> contactList = [SELECT Id, AccountId FROM Contact WHERE AccountId IN :Trigger.newMap.keyset()];
	Map<Id, List<Contact>> acctContacts = new Map<Id, List<Contact>>();
	for (Contact ct : contactList) {
		List<Contact> contacts = acctContacts.get(ct.AccountId);
        if (contacts == null) {
			contacts = new List<Contact>();
		}
		contacts.add(ct);
		
		acctContacts.put(ct.AccountId, contacts);
    }
	
   for(Account a:Trigger.new)
   {
    Decimal a1=trigger.oldmap.get(a.id).Number_Of_Contacts__c;
    Decimal a2=trigger.newMap.get(a.id).Number_Of_Contacts__c;
    Decimal a3=0;
    if(a2>a1)
    {
      a3=a2-a1;
      for(Integer i=1;i<=a3;i++)
      {
        Contact c=new Contact();
        c.lastname='Update' +i;
        c.AccountId=a.id;
        toAdd.add(c);
      }
     }
    if(a2<a1) {
		a3=a1-a2;
		List<Contact> aContacts = acctContacts.get(a.Id);
		for(Integer i=1;i<=a3;i++)
		{
			toDelete.add(aContacts.remove(0))
			
        }
	}
    }
      insert toAdd;
	  delete toDelete;
   }
   
}

 
Lakshmi SLakshmi S 
HI All,

Q). What is a Batch Apex,Queueable Apex and @Future methods?, What are the differences between them and when we are going to use these classes?
Can anyone explain these classes.......
 
Best Answer chosen by Lakshmi S
SandhyaSandhya (Salesforce Developers) 
Hi Lakshmi Narasimha,


Queueable Interface methods and Future methods are Asynchronous Apex Processes that add jobs to the job queue and each job runs when system resources become available, so it doesn’t delay the execution of the main Apex logic. They also share a benefit of having some higher governor limits than synchronous Apex, such as heap size limits (12 MB),  number of SOQL queries issued (200) and Maximum CPU time on the Salesforce servers (60k ms). But the Queueable interface methods are a step up from the future methods because they also come with these additional benefits (according to Salesforce release notes):

To define a future method, simply annotate it with the future annotation, as follows:-
 
global class FutureClass
{
    @future
    public static void myFutureMethod()
    {   
         // Perform some operations
    }
}


NOTE :-

1) Methods with the future annotation must be static methods
2) can only return a void type
3) The specified parameters must be primitive data types, arrays of primitive data types, or collections of primitive data types
4) Methods with the future annotation cannot take sObjects or objects as arguments.
5) You can invoke future methods the same way you invoke any other method. However, a future method can’t invoke another future method
6) No more than 50 method calls per Apex invocation
7) Asynchronous calls, such as @future or executeBatch, called in a startTest, stopTest block, do not count against your limits for the number of queued jobs
8) The maximum number of future method invocations per a 24-hour period is 250,000 or the number of user licenses in your organization multiplied by 200, whichever is greater
9) To test methods defined with the future annotation, call the class containing the method in a startTest(), stopTest() code block. All asynchronous calls made after the startTest method are collected by the system. When stopTest is executed, all asynchronous processes are run synchronously


IMP:-
The reason why sObjects can’t be passed as arguments to future methods is because the sObject might change between the time you call the method and the time it executes. In this case, the future method will get the old sObject values and might overwrite them.  To work with sObjects that already exist in the database, pass the sObject ID instead (or collection of IDs) and use the ID to perform a query for the most up-to-date record. The following example shows how to do so with a list of IDs


Example of a future method that makes a callout to an external service. Notice that the annotation takes an extra parameter (callout=true) to indicate that callouts are allowed
 
global class FutureMethodExample
{
    @future(callout=true)
    public static void getStockQuotes(String acctName)
    {   
         // Perform a callout to an external service
    }

}


Queueable Interface

Getting an ID for your job: When you submit your job by invoking the System.enqueueJob method, the method returns the ID of the new job. This ID corresponds to the ID of the AsyncApexJob record. You can use this ID to identify your job and monitor its progress, either through the Salesforce user interface in the Apex Jobs page, or programmatically by querying your record from AsyncApexJob.
Chaining jobs: You can chain one job to another by starting a second job from a running job. Chaining jobs is useful if you need to do some processing that depends on another process to have run first.


Below is an example of how to implement the Queueable interface.
 
public class AsyncExecutionExample implements Queueable {
     public void execute(QueueableContext context) {
          Account a = new Account(Name='Acme',Phone='(415) 555-1212');
          insert a; 
     }
}
You can add the class to a job queue by calling this method.
ID jobID = System.enqueueJob(new AsyncExecutionExample());


If you have a second class that also implements the Queueable interface and you want it to run after the class above is done, you can chain them together like this:
 
public class AsyncExecutionExample implements Queueable {
     public void execute(QueueableContext context) {
          Account a = new Account(Name='Acme',Phone='(415) 555-1212');
          insert a; 

         // Chain this job to next job by submitting the next job
         System.enqueueJob(new SecondJob());
     }
}


Thanks and Regards
sandhya

 
Lakshmi SLakshmi S 
Hi All,

Q). What is a future method ? When we are going to use Future methods? Example program for Future method and Schedulable class for Future method?

Give me reply anyone.....
Best Answer chosen by Lakshmi S
NagendraNagendra (Salesforce Developers) 
Hi Lakshmi Narasimha,

What is Future Method:

A future method runs in the background, asynchronously. You can call a future method for executing long-running operations, such as callouts to external Web services or any operation you'd like to run in its own thread, on its own time.

When to use Future Method:

If you want to make the execution of the apex program to run asynchronously then we make use of future method.When you specify
future , the method executes when Salesforce has available resources. For example, you can use the future annotation when making an asynchronous Web service callout to an external service.

Apex class with Future Method:
public class AccountProcessor 
{
  @future
  public static void countContacts(Set<id> setId) 
  {
      List<Account> lstAccount = [select id,Number_of_Contacts__c , (select id from contacts ) from account where id in :setId ];
      for( Account acc : lstAccount )
      {
          List<Contact> lstCont = acc.contacts ;
          
          acc.Number_of_Contacts__c = lstCont.size();
      }
      update lstAccount;
  }
}

Test class for the above:
@IsTest
public class AccountProcessorTest {
    public static testmethod void TestAccountProcessorTest() 
    {
        Account a = new Account();
        a.Name = 'Test Account';
        Insert a;

        Contact cont = New Contact();
        cont.FirstName ='Bob';
        cont.LastName ='Masters';
        cont.AccountId = a.Id;
        Insert cont;
        
        set<Id> setAccId = new Set<ID>();
        setAccId.add(a.id);
 
        Test.startTest();
            AccountProcessor.countContacts(setAccId);
        Test.stopTest();
        
        Account ACC = [select Number_of_Contacts__c from Account where id = :a.id LIMIT 1];
        System.assertEquals ( Integer.valueOf(ACC.Number_of_Contacts__c) ,1);
  }
  
}

Instead of a Schedulable class, try using a batch class. batch classes can be scheduled using the UI, and can call @future methods.
global class ScheduledDispatcher Implements Schedulable{

    public Interface IScheduleDispached{
        void execute(SchedulableContext sc);
    }

    global void execute(SchedulableContext sc){
        Type targetType = Type.forName('{HANDLERNAME');
        if(targetType != null){
            IScheduleDispached obj = (IScheduleDispached)targetType.newInstance();
            obj.execute(sc);
        }
    }


}

public class {HANDLERNAME} implements ScheduledDispatcher.IScheduleDispached {

  public void execute(SchedulableContext sc)
    {

        //Call your Future Method Here

    } 

}
For more information refer to the below link.
http://amitsalesforce.blogspot.sg/2015/02/future-methods-in-salesforce.html

Kindly mark my solution as the best answer if it helps you.

Best Regards,
Nagendra.P