Just to play devil's advocate, I think you may be somewhat missing the point of a generic utility method. Generic is powerful. Now you seek to pollute that. To some extent, context specific logic belongs in the calling context.
I understand that sometimes, reality doesn't play nice, and you may need to do source dependent processing. But a lot of times, those calling contexts leave artifacts. For example, what are you setting as the value of the LeadSource
field? Does it vary depending on these contexts? Are there other field indicators that can lead you to conclude which context a record was created in? My preference is to put that sort of logic in a trigger if you can conclusively determine calling context another way.
Here is the extent to which I know you can determine calling context:
Batch
- System.isBatch()
@future
- System.isFuture()
Queueable
- System.isQueueable()
Schedulable
- System.isScheduled()
Trigger
- Trigger.isExecuting
As far as I know you can't tell if you are running Execute Anonymous
, WebService
, or Visualforce
. The following might be somewhat helpful:
Visualforce
- ApexPages.currentPage() != null
Apex REST
- RestContext.request != null
You can also get a some information by querying the AuthSession
object. Not sure how reliable this approach would be but worth mention.
SELECT LoginType, SessionType FROM AuthSession
WHERE UsersId = :UserInfo.getUserId()
AND IsCurrent = true
ORDER BY CreatedDate DESC
You could also try this strategy but it's more dubious:
try
{
throw new DmlException();
}
catch (DmlException e)
{
String stackTrace = e.getStackTraceString();
if (stackTrace.contains('AnonymousBlock'))
system.debug('Execute Anonymous');
// other parsing...
}
If you really must determine the context, I was going to recommend something similar to what @Boris wrote up. However, in addition to setting a static
variable, you could consider method overloads.
public class Utility
{
public static void method(List<Lead> input)
{
// existing logic
}
public static void method(List<Lead> input, /*String or Enum*/ context)
{
method(input);
// further processing
}
}
Or you can at least move the context specific logic to another method to minimize the "pollution" factor:
public class Utility
{
public static void method(List<Lead> input)
{
// existing logic
contextLogic(input);
}
static void contextLogic(List<Lead> input)
{
if (System.isBatch()) { batchLogic(input); }
if (System.isFuture()) { futureLogic(input); }
if (System.isQueueable()) { queueableLogic(input); }
if (System.isScheduled()) { schedulableLogic(input); }
if (Trigger.isExecuting) { triggerLogic(input); }
if (ApexPages.currentPage() != null) { visualforceLogic(input); }
if (RestContext.request != null) { apexRestLogic(input); }
try
{
throw new DmlException(); // down the rabbit hole...
}
catch (DmlException e)
{
// have fun
}
}
}