5

I have a chained queuable apex class making an HTTP request to an external server. After each request comes back with a successful response, the next class will fire and make another request to a different endpoint on the same server.

My question is: Is there an advantage or difference in putting logic in the Constructor vs the Execute Method? (just out of curiosity, everything is working currently)

Ex: Both of these classes work, is one better than the other?:

Class 1 (callout seperate from execute method):

public with sharing class firstCallout implements Queueable, Database.AllowsCallouts {
  public firstCallout(){
    Http h = new Http();
    HttpRequest req = new HttpRequest();
    req.setEndpoint('https://myserver.com/endpoint1');
    req.setMethod('POST');
  //////// do things with response, update records//////
  }
  public void execute(QueueableContext context) {
    System.enqueueJob(new secondClass(testIds));
  }
}

vs

Class 2 (callout in execute method):

public with sharing class firstCallout implements Queueable, Database.AllowsCallouts {
 public firstCallout(){
   /////// now no logic is being performed here //////
 }
  public void execute(QueueableContext context) {
   Http h = new Http();
   HttpRequest req = new HttpRequest();
   req.setEndpoint('https://myserver.com/endpoint1');
   req.setMethod('POST');

   System.enqueueJob(new secondClass(testIds));
  }
}
4

I would say, the constructor is best used just as "prep". The work you want to enqueue should be done in the execute method.

You always have the option, when constructing a Queueable, to run the work synchronously by calling the execute method. E.g. I have used this pattern so I can decide based on limits or recursion whether to do the work right now or defer it. So if you put the work in the execute method, you are giving the caller a choice.

  • Not sure what the pasted link has to do with it. But yes, if you choose to run synchronously you just call the code without an enqueueJob. If you choose to run async you pass it into enqueueJob. – Charles T Nov 27 '19 at 22:28
6

The most important difference would be that constructor is executed in current execution context, and execute method is executed in new one.

In practice it mean that if you call your queueable in trigger or after DML -- it would not be possible to make callout in constructor, but only in execute method.

5

Tl;dr: I don't recommend using a constructor like this.

I think this would violate the principle of least astonishment in a few ways:

  • Constructor has logic in it (when they're normally used to populate class variables and such)
  • The execute() method doesn't contain the logic that's executed

While the effect is likely to be the same, putting your logic in the constructor is likely going to be harder to maintain because that's a different enough approach to using queueable that people (yourself included, 6 months in the future when you're forgotten about this and tracking down a bug) are going to need to spend time and mental capital to figure out how it works.

I'd also expect it to be harder to test. By putting things into the constructor, you are forcing that code to be run at the exact time (every time) that you create an instance of the object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.