Java Development News:
Pipeline to Visitor Design Pattern
By Waleed Hassan
01 Jun 2006 | TheServerSide.com
Moving from Analysis to Design phase, designers try to make the software system very maintainable through selecting all the functions that are used frequently by most of the use cases and make components out of them. These software components are usually designed in a form of utility classes that are to be called through the system. These utility classes fit well for the sake of the current system. However, the problem arises when an update in the system should be conducted, like adding an extra parameter for example to some function in the utility class to enhance some behavior in that function, then all the callers to that utility class should be made, which actually doesn't make it a component at all.
Another problem arises when some node in the flow implementing some use case changes in a way that is instead of collecting some data from a DB, for example, it has to be collected from xml, or even from a call to some web service, which is typical to service oriented architecture.
In addition, a problem would happen if some flow of the application should be exposed later in a form of a web service to be used by an external system.
The objective is to present a new design pattern - namely, Pipeline to Visitor. This pattern is supposed to handle the issue of building software components in a way that makes the software very maintainable. The pipeline to visitor design pattern is best suited in the business logic tier.
The paper goes like the following:
- Solution Overview.
- The bigger picture.
- Solution details.
- Usage briefs.
- Development process, using the new pattern.
- Working example.
Given a system analysis, which is a collection of some use cases, all the functions that are commonly used through the system are to be categorized and put in components according to category, and these components should apply the Visitor pattern. The visitors should be stateless. Independent of building all the visitors of the system, the flow of the use cases are to be implemented in objects called Pipelines that simply resemble the flow of use cases. Those Pipelines should keep the state of the use case, and call the Visitors in order to perform any common logic. The Visitors should be called in a way that later changes in their function parameters do not affect the callers, the pipelines.
Hence, calls to Visitors should be conducted using Collections, typically hashmaps.
The Bigger Picture
The following component diagram describes the Pipeline to Visitor pattern in action. Please check the structure below.
- Presentation framework is any presentation framework to be used. Please check below the Best Examples for presentation frameworks options and how the Pipeline to Visitor would be used with them. The presentation framework sends either the request to the pipeline object at the business logic tier according to the use case desired, or a collection object summing all relevant parameters for this specific use case, if the presentation framework supports that.
- Pipeline Class, this is actually the object implementing the real flow of some use case, resembling a typical sequence diagram. It resembles a flow chart, implementing the methods in the Pipeline Interface. Use case specific exceptions should be handled at this component.
- Pipeline Interface, is the interface containing the specific business methods to be used in the use case business logic flow.
- Pipeline Interface Adapter, is the adapter, to be developed, that is used to convert the Pipeline native interface, into an interface compliant with the WSDL, so that we can call this specific pipeline as a web service from an external system.
- Visitors, are the all purpose flyweight objects to be used in non specific tasks like a search, upload, parse, ePay component ... all parameters to be dealt with in calling visitors have to be in the form of collections. Visitors can also behave like facads for subsystems/components like CMS, workflow, etc. Component specific exceptions should be handled at this level. Inputs to and outputs from visitors should be in a form of a collection object.
- DAOs, are the data access objects, that can simply be mapping objects to the DB, or xml files for simple data tiers, or callers to adapters in case of connection with legacy, B2B,.. etc. DAOs are also visitors in a sense, meaning that they should be handled via collections.
- Adapters are the adapters to be used to integrate with the MOMs, legacy applications, web services in case of SOA, etc., and again they should be handled using collections.
Following is the structure and collaboration diagrams of the Pipeline to Visitor pattern, in case the presentation framework being used supports us with the actual parameters of some specific use case at a time, not in a collection format, which is not the ideal case. Please check below the process explanation.
- The presentation framework calls a business object to create a pipeline object of the use case in action, passing the specific parameters of this use case.
- The pipeline object starts the flow of that use case using some visitors, DAOs, ...
- When the pipeline needs to use the XVisitor, it calls first the init method of the visitor, passing itself as a papameter.
- The init then uses the Reflection APIs, to get the names of the attributes of the pipeline object, loops over them, and get the values of each one. The init then sums all the parameters, and values in a hashmap, and returns it to the pipeline object.
- The pipeline stores the structure hashmap, only the names of the attributes, of that specific use case in the CashManagerVisitor.
- All treatment of the XVisitor should be conducted through a hashmap, after that.
Usage briefs are listed categorized by the presentation framework options.
Presentation Framework Options
- Struts, an MVC compliant presentation application framework, in this case a dynamic form bean object gets automatically filled by the form in the front end, and goes to the action controller servlet, that forwards this form bean to the targeted action. The dynamic form bean in this case will act as the collection object in this case, and will be the main transportation parameter between the pipeline and the visitors.
- Ordinary JSPs, ASPs forms at the front end submitting the request to a controller object at the web server tire. In this case, one of two options can be used,
- A client script can be built to be called on submit of all forms, this client code will sum up all the input parameters in an xml file, and sends to the controller, which will then un serializes this xml file in a hashmap, and complete the cycle with that hashmap, passing it as a parameter to the pipeline object.
- The second option is use the forms as is, and then the reflection is to be used on the visitors' side to create the collection object and store it in the CashManagerVisitor.
- XSL templates. In this case we actually have plain html pages, as the browser has already rendered the xsl and produced the html page. Again the solution as the second option is to use as is , and the reflection will take place, or build a simple client script.
XSL templates. In this case we actually have plain html pages, as the browser has already rendered the xsl and produced the html page. Again the solution as the second option is to use as is, and the reflection will take place, or build a simple client script.
- UCD developers, to develop the forms.
- Visitor developers, to develop general purpose frequently called components, to be defined at the design phase.
- DAO & Adapters developers, to develop direct DB mapping objects, and legacy, B2B wrapper objects.
- Pipeline developers, to develop the use case flows.
Obviously, all the above-mentioned developers will work in parallel as there is no intervention between any of them.
Following is a working example of using the Pipeline To Visitor (P2V) pattern.
It's intended to do a comprehensive application for e-services, for citizens and employees, that is composed of the following modules:
- Telecom services.
- Applying for a leased line.
- Applying for a phone.
- Paying phone bills.
- Complaining about a bad service
- Reading content about the mission statement of this service provider.
- Foreign affairs services.
- Applying for a passport.
- Renewing a passport.
- Education services.
- The first thing to do is to sum up all the above requirements in categories according to processes. That is to say that, instead of thinking module wise, all the system is to be
traversed horizontally. In this case, we have the following (Business Perspective):
- Application request.
Some application request (regardless of the business flow behind it) to be submitted, passed to some workflow, and enquired by the user to check up its status
Some contents, to be authored by the editor, reviewed by the reviewer, and displayed for the end user / and or employee according to privileges.
- Roles management.
Some roles to be defined by the admin, so that any content is to be edited, and or viewed according to some privilege.
- Application request.
- The second round is to traverse each category's use cases to sum up all the building components in each category (Technical Perspective), that is :
- Application request.
- Upload component.
- Business validation component.
- Workflow component, that is a façade for some workflow engine.
- Search component.
- Download component.
- ePayment component
- Integration adapter, to retrieve relevant information about the citizen from external systems.
- Indexing component.
- Media repository component.
- Ultra search component.
- Folders management component, for handling web folders component.
- Roles management component, that might be a façade for some LDAP compliant server, to handle roles of groups and individuals.
- Application request.
- The third round is to treat all the above components are to be treated as visitors, except for the integration adapter, as it will be treated as an adapter, such that all the interaction with them will be conducted using collection object so that maintenance is preserved, that is no change in the whole code should be done if for example, the way contents are to be manipulated is changed, a different workflow engine is to be used, some information from inside the system is to be retrieved from external system, or some service is to be exposed to external systems in a form of a web service.
- The final round in the architecture using the P2V pattern is to figure out the whole picture of some category like the following:
Assuming the Struts is to be used at the presentation tier, following is the component diagram for the Application Request process:
Note that the collection object used here is the struts dynamic form object.
About the Author:
Waleed Hassan El-Said Abd El-Salam is assistant lecturer of computer science at Ain Shams University. He is also a software architect.