mitchspano/apex-trigger-actions-framework

System.TypeException : Apex Class does not have a no-arg constructor

Closed this issue · 2 comments

rarpit commented

Expected Behavior

Framework should query records without throwing exception.

Actual Behavior

System.TypeException : does not have a no-arg constructor

Steps to Reproduce the Problem

Followed documentation for https://github.com/mitchspano/apex-trigger-actions-framework#avoid-repeated-queries

  1. Create an Apex class to query SOQL records (TA_Opportunity_Queries)
  2. Open Execute Anonymous Window
  3. Execute - Object triggerInstance = Type.forName('TA_Opportunity_Queries').newInstance();
    Above statement is equivalent to MetadataTriggerHandler (line 192).
  4. System.TypeException: TA_Opportunity_Queries does not have a no-arg constructor.

Specifications

  • Version: current
  • Platform: salesforce

Hello @rarpit - thank you for checking out the framework and raising this issue.

In the documentation, you can see that we author an inner class called Service which is the Trigger Action, and the top level class is the Singleton.

public class TA_Opportunity_Queries {
  private static TA_Opportunity_Queries instance;

  private TA_Opportunity_Queries() {
  }

  public static TA_Opportunity_Queries getInstance() {
    if (TA_Opportunity_Queries.instance == null) {
      TA_Opportunity_Queries.instance = new TA_Opportunity_Queries();
    }
    return TA_Opportunity_Queries.instance;
  }

  public Map<Id, Account> beforeAccountMap { get; private set; }

  public class Service implements TriggerAction.BeforeInsert {
    public void beforeInsert(List<Opportunity> newList) {
      TA_Opportunity_Queries.getInstance().beforeAccountMap = getAccountMapFromOpportunities(
        newList
      );
    }

    private Map<Id, Account> getAccountMapFromOpportunities(
      List<Opportunity> newList
    ) {
      Set<Id> accountIds = new Set<Id>();
      for (Opportunity myOpp : newList) {
        accountIds.add(myOpp.AccountId);
      }
      return new Map<Id, Account>(
        [SELECT Id, Name FROM Account WHERE Id IN :accountIds]
      );
    }
  }
}

So the Apex_Class_Name__c value on the Trigger_Action__mdt row should be:

TA_Opportunity_Queries.Service

image

image

System.Savepoint sp = Database.setSavepoint();
Account acme = new Account(Name = 'Acme');
insert acme;

Opportunity opp = new Opportunity(
    Name = 'Sample Opportunity',
    CloseDate = Date.today(),
    StageName = 'Prospecting',
    AccountId = acme.Id
);
insert opp;

opp = [SELECT Id, Name FROM Opportunity WHERE Id = :opp.Id];
System.Assert.areEqual('Acme | Sample Opportunity', opp.Name);
Database.rollback(sp);

The system is working as intended, so I will close this issue, but I will also update the documentation to make this clearer for future readers.

rarpit commented

Thank you @mitchspano for quick resolution.