Methods to shift your enterprise.TM  

Execution Context

Provides a context between a client and a service that is limited in scope only to the current execution bounds and that facilitates the safe access to crosscutting parameters to various application layers.

executioncontextsummary

Background

There are times when a client may need to provide extra parameters to a service, but because of the kind of parameters they are the service designer opts not to support them as part of the published API. Even so the service still has a contract to honor the extra parameters if they are provided. Thus we need a means to supply the extra optional parameters, and which must be guaranteed to be unique for and visible only to the current execution context boundaries (e.g. an HTTP request). The facility is called an execution context.

While this is somewhat of a crosscutting concern, it is not necessarily best to solve this problem using aspect-oriented programming (AOP). In the cases where this pattern applies, the kinds of parameters and how they are used does not lend itself to applying AOP.

For example, I like to use an execution context when supporting the Domain Dependency Resolver pattern for lazy loading resolutions. If I were to require every service method to provide an extra parameter naming the Domain Dependency Resolver of choice, it would cause a lot of “noise” on the API. I'd have hundreds of methods that all take a certain kind of parameter, which in some cases would just be passed as null.

Value and Benefits

An execution context is invaluable when you have one or more data parameters that would otherwise have to be passed as a parameter to one or more service methods, or even into the domain model layer. To appreciate the value of this pattern it may be best to consider life without it. Say that you have services that used other services and a domain layer and integration/data layer. Now imagine that all up and down the service, domain, and other layers the crosscutting parameter(s) need to be passed on many methods. You can quickly imagine that your service API and domain model will be completely littered with the parameter(s), clouding your view of the real purpose of each of the methods.

You will therefore benefit by having to think of fewer parameters, but still to be able to access them wherever and whenever they are needed.

Of course caution is in order. If you use your execution context as a general purpose “global data” segment instead of passing appropriate parameters to your services and object on other layers, you'd soon realize anti-patterns such as “blob,” “spaghetti,” or “big ball of mud” (take your pick).

Putting It to Work

The primary trick to implementing an Execution Context that properly minds the boundaries of the current request thread of execution is to associate the execution context object instance with the thread. In a web-based application (client-server or enterprise) each user request to the application is handled via some form of HTTP request. The underlying web server/container that is handling the unique request is running within a thread allocated specifically and uniquely to the request. Clients associate the execution context object instance with that thread. Require that each consumer of the execution context object retrieve it by providing the same thread identifier that was used by the client to associate it with the current context thread. In languages such as Java and C# there is built-in support to make this very easy to do.

On class ExecutionContext itself provide accessor methods (or get/set properties in C#) to allow clients to set context properties and for consumers to get them. Limit the gets/sets to only the specific types of objects that are carefully identified as crosscutting by design. It may be desirable to provide multiple ExecutionContext interfaces, each with specific kinds of property accessors based on the limited kinds of parameters that should be accessed by a given client/consumer. For example, web MVC controllers may want to specify a required Domain Dependency Resolver that a service must fulfill. So provide an interface that allows the client only to specify and service only to get the identified resolver. In turn don't put accessors on the interface that the client will use that would allow the client code to set a Unit of Work or some other object that is clearly out of scope for a web controller. Of course each interface is implemented by just one ExecutionContextImpl:

executioncontextinterfaces

Note that getDomainDependencyResolverIdentifier() is declared in the above interfaces twice, once in the service-specific and once in the domain-specific interface. This just emphasizes that you may desire to fulfill the resolver in one or the other layer. See pattern Domain Dependency Resolver for details.

Reference Implementation

The following is a basic implementation of Execution Context for in C#:

using System;

public class ExecutionContext
{
    [ThreadStatic]
    private static ExecutionContext instance;

    public static ExecutionContext Instance
    {
        get
        {
            if (ExecutionContext.instance == null)
            {
                ExecutionContext.instance = new ExecutionContext();
            }

            return ExecutionContext.instance;
        }
    }

    public void Release()
    {
        ExecutionContext.instance = null;
    }
    private ExecutionContext()
    {
    }
}

The C# implementation achieves thread of execution association using the special [ThreadStatic] attribute. This implementation hides the class's constructor so that only one instance may be created; that is the Singleton pattern. Use the Instance static property getter to get the current thread's ExecutionContext instance, and Release method to clear it. Note that Release is provided only for special convenience. It is generally not used since the context changes as threads are recycled during each request. Of course you will add various instance property accessors (get/set) as needed.

The Java implementation uses the Java standard ThreadLocal class:

package com.shiftmethod.todo.common;

public class ExecutionContext {

    private static final ThreadLocal holder =
        new ThreadLocal();
    
    public static ExecutionContext getExecutionContext() {

        ExecutionContext tempExecutionContext = holder.get();
        
        if (tempExecutionContext == null) {
            
            tempExecutionContext = new ExecutionContext();
            
            holder.set(tempExecutionContext);
        }
        
        return tempExecutionContext;
    }
    
    private ExecutionContext() {
        super();
    }
}

Again, add the appropriate properties and accessors. If your execution context is used across various application architectural layers you may benefit further by using the multiple interface approach from the Putting It to Work section.

Consequences

You will find tradeoffs among the following competing forces. Benefit from reduced clutter and avoid pattern abuse like the plague.

  • Reduce API and Layer Clutter: When properly applied the Execution Context will become a very useful ally and make your services API and other special crosscutting parameter consumers much more readable.

  • Avoid Abuse with Anti-Patterns: Execution Context is not meant to sidestep software development best practise. There are clearly practical applications, bad, and plain wrong applications. If you start overloading your execution context with more than say a few or at most half a dozen possible crosscutting parameters, you could likely be abusing the pattern.

Related Patterns

The following are the kinds of patterns and other application resources that Execution Context fits hand-in-glove with.

  • Domain Dependency Resolver: The resolver that you choose use to lazy load specific domain aggregates can be identified using an Execution Context. This frees your API from having to support the resolver identifier, and allows each use case realization to either identify its needed resolver or to determine that none is needed.

  • Security Token: While I don't of necessity codify this pattern, you can imagine the need to “pass” a session based security identifier (perhaps with considerable baggage) around your service API and other layers, even if you are using AOP-based security. If this is the case place your Security Token in your execution context.

  • Storage Session, Unit of Work, Repository: Whether you are using a Domain Model with an Object-Relational Mapping tool or some other persistence mechanism, it will greatly reduce the complexity of dealing with sessions, units of work (transactional contexts), database connections, etc., within a complex single request fulfillment if you place such resources into an execution context. If you avoid passing such necessary resources around as parameters to various service methods, domain layer objects (e.g. Repository), integration layer, etc., your API and various objects will be more reusable. Note that the Spring Framework provides an Execution Context kind of facility via its HibernateTemplate and SpringSessionContext. However, those classes are limited to supporting persistence sessions only, not any arbitrary crosscutting parameters.