Type.forName() – Create apex class instance using class name

How many of you are aware that after summer 12 release, we can create Apex Class instance dynamically just by using class name?

Yes, no need to specify class type to create class instance. Here is how you can do it:

Type t = Type.forName('YourClassName'); //Create a type object using class name 
YourClassName newObj = (YourClassName)t.newInstance(); //create a instance using Type object and TypeCast to your class
One challenge you will still see, that you need to specify your Class Type in 2nd line, which kind of does not suit our need as we need it completely dynamic.

 

Use Interface to make it completely dynamic

So lets say, you are using a managed package and you want to validate user password to have minimum 6 characters. You implement the logic, everything works fine and everybody is enjoying your manages package service. But wait, what if some customer wants to enforce 8 character password? You have to modify your apex code for this which is not a good idea. So lets leverage the use of Type.forName function here to create this functionality:

global interface PasswordInterface { //create a interface with checkPassword method
     boolean checkPassword(String pwdString);
}

Now lets say you have a class named SixCharacterPassword that enforces 6 character password:

global class SixCharacterPassword implements PasswordInterface{

     global boolean checkPassword(String pwdString){

     return pwdString.length() >=6;

     }

}

Also you have one more class name EightCharacterPassword that enforces 8 character password:

global class EightCharacterPassword implements TestInterface{

     global boolean checkPassword(String pwdString){

     return pwdString.length() >=8;

     }

}

 

Now based on your requirement you can select which apex class you want to use. Below is the Factory Class to select the apex class based on your requirement

global class PasswordClassFactory {
    public static PasswordInterface getPasswordClass(){
        String defaultClass = SixCharacterPassword.class.getName();
        String customClass;

        Password_Impl__c settings = Password_Impl__c.getInstance('Password Validation'); //customer setting to check configuration

        if (settings != null && settings.Password_Validation_Class__c != null) {
            customClass = settings.Password_Validation_Class__c;
        }
        else {
            customClass = defaultClass;
        }

        Type t = Type.forName(customClass);
        PasswordInterface passwordClass = (PasswordInterface)t.newInstance();
        return passwordClass;
    }
}

 

And this is how you can call above factory class from your Trigger

trigger CheckPassword on CustomUser__c (before insert, before update) { 
    PasswordInterface passwordClass = PasswordClassFactory.getPasswordClass(); 
    for (CustomUser__c c: Trigger.new) { 
        if (c.Password__c != null && !passwordClass.checkPassword(c.Password__c)) { 
           c.addError('Invalid Password'); 
        } 
    } 
}

 

What would be another best use case for this?

Thanks to my colleague Suman for giving me this amazing use case of this dynamic functionality. His requirement was

There is a custom object which stores the Schedulable Apex Classes. The requirement is to create Schedulable apex jobs for all of them using System.schedule method but it allows only instance of a Schedulable apex class as an input parameter, and not able to create an instance using the class name. 

This is how we have done this:

QJobsList = [SELECT id, Name,  Job_Name__c, Apex_Class__c FROM Schedule_Apex__c ];
for(Schedule_Apex__c wa : QJobsList){
   Type t = Type.forName(wa.Apex_Class__c); //create Type instance
   Schedulable classInstance = (Schedulable) t.newInstance(); //Create schedulable interface instance

   //Cron Expression
   String sch = '0 0 0 '+ wa.Scheduled_Date__c.day() + ' ' + wa.Scheduled_Date__c.month() + ' ? ' +    wa.Scheduled_Date__c.year(); //
            
   System.schedule( 'Test job1' , sch , classInstance); //pass schedulable interface instance here
}

 

This is one of the great feature introduced in Summer 12. Please make use of it wherever possible. Use Interface for complete dynamic approach.

 

Please do share your feedback and suggestions. Thanks!!

Manish Choudhari

I am a certified Salesforce Application & System Architect and Developer working on Salesforce Technology since 2014. Currently, I have 14 Salesforce certifications along with OCPJP (Oracle Certified Profession JavaSE6 Programmer) working in Salesforce.com Hyderabad as a Technical Engineer. Writing technical blogs, learning new technologies and frameworks and sharing knowledge is my hobby.

This Post Has 7 Comments

  1. Avatar

    Thanks for taking up this Manish.
    Good Job.

  2. Avatar

    Manish,
    I have been trying to achieve this requirement since couple of days, you made it possible at last. You are such an amazing developer, Please keep going it.. Thanks for all your patience in writing very good blogs.

    Cheers,
    Suman

  3. Avatar

    global class SixCharacterPassword implements TestInterface (or)
    global class SixCharacterPassword implements PasswordInterface .
    iam a follower of ur posts,little confusing in this regard..

    1. Avatar

      Hi Srinu,

      Thanks for pointing it out. The class should implement PasswordInterface. I have updated the code.

      Thanks

      1. Avatar

        thanks manish

  4. Avatar

    I have the same rereuirement as mentioned.
    There is a custom object which stores the Schedulable Apex Classes.
    The requirement is to create Schedulable apex jobs for all of them using System.schedule method but it allows
    only instance of a Schedulable apex class as an input parameter, and not able to create an instance using
    the class name.

    QJobsList = [SELECT id, Name, Job_Name__c, Apex_Class__c FROM Schedule_Apex__c ];
    for(Schedule_Apex__c wa : QJobsList){
    Type t = Type.forName(wa.Apex_Class__c); //create Type instance
    Schedulable classInstance = (Schedulable) t.newInstance(); //Create schedulable interface instance

    //Cron Expression
    String sch = ‘0 0 0 ‘+ wa.Scheduled_Date__c.day() + ‘ ‘ + wa.Scheduled_Date__c.month() + ‘ ? ‘ + wa.Scheduled_Date__c.year(); //

    System.schedule( ‘Test job1’ , sch , classInstance); //pass schedulable interface instance here
    }

    Same above code I tried but its giving error as system.schedule does not take schedulable interface as paramerter.
    Can someone help here?

Leave a Reply to Sharath Kanukuntla Cancel reply

Close Menu