Applications deal with flow of control of code. More specifically,in a web application, every user triggered action (such as a click of a button or an AJAX call or the request for a page) can be viewed as a flow. This flow is serviced typically by a controller which in turn delegates to various facades or other classes to accomplish the business logic that is enshrined in the flow requirements. Similar arguments hold good in the Middleware Layer as well. The facades for various services can be viewed as triggering flows individually.
These flows are typically within the same JVM or application server. As such, these should be viewed as micro flows. Micro flows can be distinguished from macro flows which may span across multiple enterprise wide components. Some of the salient features of micro flows are:
Most applications are structured to implement these flows in a monolithic way. Individual classes impement business logic. One class invokes the other to implement the entire flow. Any change in the flow logic means changing this execution. As micro flows get complex, it makes sense to segment the functionality between components that provide the logic of the flow and those that orchestrate the flow. Thus there is a need for a special orchestrator which is able to call the correct set of components given a flow and accomplish the business logic that is required thereon.
Look at flow orchestrations for further notes.
Commands implement the command pattern. They are simple and testable units of work that can be implemented by independent teams.
Implements the chain of responsibility pattern. A Chain is a series of commands that have been stitched together to execute in sequence. The chain terminates if one of the commands throws an exception or when all the commands have been executed.
Routers help the flow of execution to route to one or other chains (or routers) depending on the contents of the Context.
The Context object is the value object that gets passed in the command chain. It is mutable by the commands and is progressively enhanced.
Several configuration files can exist with the same name (e.g.: META-INF/owiz.xml) in the deployment. They can get discovered and the contents would be merged to form a potentialy complex command chain. This facilitates modularization.
The best way to segment a complex flow orchestration is to individually write pieces of application functionality in separate classes and "string" these classes together to form a complex flow. This "stringing" process is accomplished using OWIZ. However, the application itself has to provide the individual classes that implement the functionality.
The classes must implement the Command pattern. OWIZ strings them together using some configuration information and voila! we have the required functionality implemented. OWIZ ships with a "configurer" that uses XML based configuration. Other configurations can be trivially possible in OWIZ. In its previous incarnations, I had made a configurer that extended the Spring configuration. OWIZ leverages a bean factory like the spring bean factory and would work best with it.
Let us illustrate OWIZ's features with a web based tax application called TAXWIZ, that needs to compute tax for an individual. The tax computation flow, so to speak, would have specific nuances that need to be taken into account to compute tax. The base application may use the salary information to compute tax. There would be a SalaryCommand for instance that can utilize the salary information to compute tax.
There may be other commands such as RealEstateCommand and InvestmentsCommand. These would compute the tax from alternative sources of income (in addition or in lieu of salary) such as real estate income and income from investments respectively.
OWIZ allows new modules to be "discovered". Module specific configuration files can extend the base configuration files to add module specific functionality for particular flows such as the tax computation flow for instance, in the above example.
This feature would be a great way to launch products that support plug in functionality. As the Real Estate module gets discovered, the RealEstateCommand would get plugged into the tax computation flow. OWIZ's ability to add the tax computation functionality piecemeal, allows TAXWIZ to implement this plug in functionality easily.
The context object encapsulates the information that has to flow from one command to the other. Context objects can be any kind of objects. OWIZ uses a "generic" for a Context object that allows it to support any kind of object. The context, typically, includes request specific information. It is advisable to keep information that is request agnostic (such as domain objects for instance) out of the context. Instead, it makes sense to utilize some other ways of accomplishing the caching of those objects (see Value Object Wizard (VOW) for example). TAXWIZ must not store income related to specific individuals in the context. It must leverage some cache to look up these domain objects.
There are three types of context information that are usually captured.
Since the functionality is implemented in the form of commands that implement the same interface, it is possible to come up with decorators that implement the same Command interface and delegate functionality to AOP alliance like aspects. This is work in progress and would be implemented for future iterations. Meanwhile, the command is perfectly free to benefit from the AOP available from other IOC frameworks such as Spring.
Attachable Command is an interface that is supported by OWIZ. An attachable command is a command that allows other commands to attach themselves to it. This provides an extensible way of controlling the execution of one command from another. Currently, the following attachable commands exist as part of the framework: