A lightweight 2PC Transaction model that provides basic data update atomicity, consistency, and isolation services to synchronize multiple Resources, such as external database servers as well as core buffer and caching structures.

Usage:

A component wants to trigger a transactional update of a resource, which may be Transaction aware at some point in the call chain.

Transactions are scoped to Threads, and so the call chain must fall within the bounds of the try block.

The component initiates a Transaction:

		try
		{ 
			Transaction transaction 
				= Transaction.startContextTransaction(Transaction.Nesting.PROPOGATE);
			
			// do some work here
			
			transaction.commit();
		}
		finally
		{
		  transaction.complete();
		}
	

A transaction-aware component in the call-chain gets a request to do some work.

		public void doMyWork()
		{
			Transaction transaction 
				= Transaction.getContextTransaction(); 

      if (transaction!=null)
      { 
        try
        {
          MyBranch myBranch=transaction.branch(getMyResourceManager());
      
          // Do some work
          myBranch.updateMyData(...);
          
        }
        catch (MyBad x)
        { 
          myBranch.rollback();
        }
        
			}	
			else
			{ throw new MyBad("Transaction required");
			}
		}
		
	

The MyBranch instance Branch changes some transactional data. It is created from the MyResourceManager instance, which demarcates an independent resource pool, and creates MyBranch. The implementation details are application specific.

    
    public class MyBranch
    {
      public void rollback()
        throws TransactionException
      {
        // Undo any changes that were made like nothing happened
      }

      void prepare()
        throws TransactionException
      {
        // Make sure we're ready to commit
      }
      
      void commit()
        throws TransactionExeption
      {
        // Make changes permanent
      }
      
      void complete()
      { 
        // de-allocate any resources
      }
    }
  
  /**
   * Attempt to commit this branch of the Transaction
   */
  void commit()
    throws TransactionException;
  
  /**
   * Deallocate any resources consumed by the branch
   */
  void complete();
    }
  
	

The purpose of the spiralcraft.lang package is to provide an EL based integration layer that can tie together application components that have not been built to be aware of each other. The integration layer is geared towards maximizing expressive power and minimizing coupling, from a developer's perspective, while maximining concurreny and minimizing per-thread resource utilization.

The EL is implemented through the creation of Channels from compiled Expressions. These Channels are bound to data sources exposed by the application via a hierarchy of Focus objects.

A Channel is a bidirectional "pipe" through which data moves. A Channel is linked to other Channels as an analog of the Expression structure, and as defined by "pseutotypes" called Reflectors.

A Reflector resolves "parameterized names", and is a fascade for whatever typing system (or lack thereof) is being exposed. A Reflector for java.lang.Class is included, which provides a java.beans "default" mapping and provides access to Object methods and properties.

A common use of this package is to provide a reusable set of View-Controller components, such as WebUIs, GUIs, templates, monitors, etc., with a means to interoperate with different Model architectures, often in the same system, using Expressions and "psuedotypes" (spiralcraft.lang.Reflector) to map query and input Channels (spiralcraft.lang.Channel) into a given application model.

The spiralcraft.lang package has two modes of extension.

Specifically, the spiralcraft.lang package supports the following characteristics:

Implementation Overview

Expressions may be parsed from text into a parse tree made up of Nodes (spiralcraft.lang.parser.Node). See Expression.parse().

The Node Tree may be programatically created by direct manipulation of Nodes to avoid text processing. Likewise, a Note Tree tree may be analyzed to determine the logic being performed and optimize it or translate it into another language (for example, SQL).

A static cache is maintained to avoid parsing the same Expression more than once. Identical text will always result in an identical Node tree.

An Expression is bound to a Focus to create a Channel.

A Channel is a bidirectional data window or pipe which supports a simple get() and set() interface. Calling get() is equivalent to evaluating the expression. Calling set() is applicable if the expression is "reversible"- for instance a data element that is retrieved may sometimes be altered.

The data handled by the Channel is defined by a Reflector, a pseudo-type which describes the set of names and operations available to the EL specific to the data provided by the channel. Since different containers may provide access to different typing systems (ie. Beans, SQL, etc), the Reflector serves as a "fascade" so the the spiralcraft.lang package can use the "services" provided by a type system in a standard fashion.

A Focus is a "starting point" provided by a container for EL evaluation. It exposes the set of data sources available to an Expression. It normally references some "default" Channel called a "subject", which is the primary target against which the expression will be evaluated. This subject Channel is usually provided by the container, which sets up the environment and scenario for the use of the spiralcraft.lang package.

An Expression may specify, using a qualified Focus specifier enclosed in square brackets, an alternate Focus against which to evaluate the expression. The name may map to a URI mapped from the type or supertype of the subject of the focus, and/or to a URI set up by the container to identify the integration point represented by the Focus. It may additionally identify an application layer associated with this integration point.

The focus Specifier is resolved by virtue of the primary Focus delegating to a "parent" Focus or to other referenced Focus objects to search for the alternate Focus name. The specific organization of Focus objects is intimately related to the structure of the actual application.