Find your content:

Search form

You are here

Call Apex class method on the fly (dynamically)

 
Share

Is there any way I can call apex method from class if both class name and method are stored in the string.

String strClass = 'BatchUtil';
String strMethod = 'updateAccounts'

now I want to call above method.. is it possible ?

I was doing research and came across following - (not sure how this works and how to call it from salesforce)

ExecuteAnonymousResult[] = binding.executeanonymous(string apexcode);

http://www.salesforce.com/us/developer/docs/apexcode/Content/sforce_api_calls_executeanonymous.htm


Attribution to: Prafulla Patil

Possible Suggestion/Solution #1

With the Callable interface that was introduced in Winter '19 you can now build a light weight interface for the methods you want to dynamically call from a class.

The example below is from the docs (tweaked to show dynamic method naming):

Example class you want to dynamically call

public class Extension implements Callable {

   // Actual method
   String concatStrings(String stringValue) {
     return stringValue + stringValue;
   }

   // Actual method
   Decimal multiplyNumbers(Decimal decimalValue) {
     return decimalValue * decimalValue;
   }

   // Dispatch actual methods
   public Object call(String action, Map<String, Object> args) {
     switch on action {
       when 'concatStrings' {
         return this.concatStrings((String)args.get('stringValue'));
       }
       when 'multiplyNumbers' {
         return this.multiplyNumbers((Decimal)args.get('decimalValue'));
       }
       when else {
        throw new ExtensionMalformedCallException('Method not implemented');
       }
     }
   }

   public class ExtensionMalformedCallException extends Exception {}
}

Unit test demonstrating the dynamic calling

@IsTest
private with sharing class ExtensionCaller {

   @IsTest
   private static void givenConfiguredExtensionWhenCalledThenValidResult() {

      // Given
      String className = 'Extension'; // Variable to demonstrate setting class name
      String methodName = 'multiplyNumbers'; // Variable to demonstrate setting method name
      Decimal decimalTestValue = 10;

      // When
      Callable extension = (Callable) Type.forName(className).newInstance();
      Decimal result = (Decimal) extension.call(methodName, new Map<String, Object> { 'decimalValue' => decimalTestValue });

      // Then
      System.assertEquals(100, result);
   }
}

Attribution to: Clint

Possible Suggestion/Solution #2

Now this is possible in apex using Tooling API.

> ToolingAPI x = new ToolingAPI(); ToolingAPI.ExecuteAnonymousResult
> toolingResult = x.executeAnonymousUnencoded("Your apex code as a
> string here");

Please refer blog post - http://codefriar.wordpress.com/2014/10/30/eval-in-apex-secure-dynamic-code-evaluation-on-the-salesforce1-platform/

ToolingAPI class is taken from here - https://github.com/afawcett/apex-toolingapi/blob/apex-toolingapi-rest/src/classes/ToolingAPI.cls


Attribution to: Prafulla Patil

Possible Suggestion/Solution #3

While you can instantiate a class based on its name using the Type system class, you can't dynamically locate a method and execute it. The best that you can do is to dynamically create an instance of a class that implements an interface and execute one of the methods on the interface.

There's more information on the Type class and an example in the :

Apex Developer's Guide


Attribution to: Bob Buzzard

Possible Suggestion/Solution #4

Update

Based on Kevin's post about adding EVAL() in Apex I created a variation that parses the response out of the Debug log. This uses the Apex API rather than the Tooling API. See Adding Eval() support to Apex.

With this you can do things like:

string output = soapSforceCom200608Apex.evalString('string first = \'foo\'; string second = \'bar\'; string result = first + second; System.debug(LoggingLevel.Error, result);');  
System.assertEquals('foobar', output);  
System.debug(output); 

The answer to How to use/invoke "execute Anonymous" calls from Apex/Controller is:

You can't invoke executeAnonymous from another block of Apex. Execute anonymous is a separate entry point to compile & run a routine which can only be invoked through the API verb - see the apex WSDL: /services/wsdl/apex

So you could in theory import the Apex WSDL back into Salesforce, which would give you binding from your example. Then you just need to build up a string with the Apex code that you would pass into the execute anonymous method. See update above for sample implementation.

You could use the article Calling Salesforce Web Services Using Apex as an example, substituting the apex WSDL for the partner API WSDL.


Attribution to: Daniel Ballinger
This content is remixed from stackoverflow or stackexchange. Please visit https://salesforce.stackexchange.com/questions/1035

My Block Status

My Block Content