Skip to content

The RequestContext interface provides access to the context of a transaction. This allows you to pass data from the initial firing to subsequent triggers within the same transaction.

For example, initiating a request from an action which causes other triggers to execute, including nested triggers. As triggers execute through a thread of execution, some triggers along the execution sequence may need context from previously executed logic. This is especially needed when executing the same trigger multiple times within the same request transaction, for example, once for the current record, then subsequent execution in nested triggers on the same object. The subsequent firing may need to run different logic than the initial firing.

You can share some data using RequestContext to set a named context and get the named context value anywhere along a request transaction in downstream triggers. The maximum amount of data you can share is 5 MB per transaction request. The value you can set must be one of the value types specified in RequestContextValueType, or an implementation of the RequestContextValue interface.

Note that a value stored in RequestContext requires an explicit getValue and setValue whenever you want to change the value. If you change the state of your RequestContextValue object, you must call setValue to put the mutated object back into the RequestContext.

To properly debug uses of RequestContext, all code that uses the context should be in the debugger. If not, the value of the context may be inaccurate, especially if you have a context value set by code already deployed to Vault and that code is absent from your debugger. Any code that uses getValue and setValue should be in your debugger.

The following is an example of using RequestContext. First, a trigger named ProductBuildRegionMap sets up a RequestContext:

@RecordTriggerInfo(object = "product__v", name = "product_region__c", events = {RecordEvent.BEFORE_INSERT}) public class ProductBuildRegionMap implements RecordTrigger { public void execute(RecordTriggerContext recordTriggerContext) { List<String> productRegions = VaultCollections.newList(); recordTriggerContext.getRecordChanges().stream().forEach(recordChange -> productRegions.add(recordChange.getNew().getValue("region__c",ValueType.STRING))); // Create a new region country map for all regions in this request and set the map into the "regionCountryMap" // request context, so that this map can be used by other triggers that execute after this one. RegionCountryMap regionCountryMap = new RegionCountryMap(productRegions); RequestContext.get().setValue("regionCountryMap", regionCountryMap); } }

Next, we have a user-defined class which implements the RequestContextValue set up in ProductBuildRegionMap.

@UserDefinedClassInfo(name = "regioncountrymap__c") public class RegionCountryMap implements RequestContextValue { private Map<String, List<String>> regionCountryMap = VaultCollections.newMap(); RegionCountryMap (List<String> productRegionId){ // Constructor to create a regionCountryMap <region, countries> by querying the Region object // to retrieve countries in the provided regions. } Map<String, List<String>> getMap () { return regionCountryMap; }; }

Lastly, our ProductCreateRelatedBrands trigger executes after the ProductBuildRegionMap trigger. It retrieves the RequestContextValue and modifies the Map inside the context.

@RecordTriggerInfo(object = "product__v", name = "product_region__c", events = {RecordEvent.AFTER_INSERT}) public class ProductCreateRelatedBrands implements RecordTrigger { public void execute(RecordTriggerContext recordTriggerContext) { // Get the RegionCountryMap from the request context RegionCountryMap regionCountryMap = RequestContext.get() .getValue("regionCountryMap", RegionCountryMap.class); // Get the map of regions and countries Map<String, List<String>> map = regionCountryMap.getMap(); // ... create specific brands for each country in a region // Remove a region from the map if brands for that region already exists and set the map back to the // request context in order to update request context with the changed map. map.remove("Asia"); RequestContext.get().setValue("regionCountryMap", regionCountryMap); } }

RequestContext supports the following user types, which are listed in the RequestContextUserType Enum:

  • INITIATING_USER: The user who initiated the request. This can be either a human user or the Vault System. This value is immutable.
  • REQUEST_OWNER: The user who currently owns the request. This will usually be the same as the INITIATING_USER, but the value can change during a workflow.

HttpService and ConnectionService each provide methods to determine if a request will succeed with a specified user type and to create a new request with a specified user type.

RequestExecutionContext provides contextual information about the current request. The following example determines if the current request takes place within a workflow and, if it does, retrieves the workflow ID, workflow name, and workflow owner ID. Learn more in the Javadocs.

LogService logService = ServiceLocator.locate(LogService.class); if (RequestContext.get().containsRequestExecutionContext(WorkflowRequestExecutionContext.class)) { WorkflowRequestExecutionContext workflowRequestExecutionContext = RequestContext.get().getRequestExecutionContext(WorkflowRequestExecutionContext.class); logService.debug("workflowId = {}", workflowRequestExecutionContext.getWorkflowId()); logService.debug("workflowName = {}", workflowRequestExecutionContext.getWorkflowName()); logService.debug("workflowOwnerId = {}", workflowRequestExecutionContext.getWorkflowOwnerId()); } else { logService.debug("Not in a workflow");