Generic Design for an iManager Plugin

22 Dec 2004

Problem:

Many plugins have a huge Class which extends, executes and implements all handlers. There are a host of Utility files which are copied for every plugin.

Objective:

  • Introduce layers.
  • Implement Design patterns in this existing design.
  • Arrive at a generic design which can be used for any plugin development. Maximize reuse.
  • Come out of Method handlers - Procedure Oriented programming to Object handlers - Object Oriented Programming.
  • Allow easy code generation from plugin specification.

Existing design has a controller class which is tightly coupled to all details. To write a new plugin, a lot of changes are required.

So, the new Controller is designed for minimal responsibilities. The class which extends dev.Task has these responsibilities

  1. Implement Execute, it is the purpose of this class
  2. Handle Should Run, as it is the first Expert to get the HttpServletRequest

What needs to be done in the execute?
Execute should make this task a Controller.
Execute should send the request to next controller based on a criteria.

Criteria may be the JSP page which submitted the form.
Hence execute diverts the request to Page Handler. Task Controller has all pages in the Task. So every page when added to the plugin results in a LOC addition only in task controller.

PageHandler
Should divert the request to Button/Action Handler. PageHandler has all action Handlers for a page. An action is a submitting action in browser. It may be OK, CANCEL, REFRESH… All actions need not be user-generated, there may be periodic REFRESH done by JavaScript thread. Every action requires 1 LOC addition only to the PageHandler.

ActionHandler
Needs to do some action, involving state change and error handling.
Action handlers consider state information and invoke appropriate workers.

Worker
Performs a specific task. After the task, sets the Next JSP page. ActionHandlers exist in Application layer, while workers are in Domain layer.

This chain of responsibility design needs to answer these Qs:

Who is responsible to maintain state?
Where is session specific info stored?
How are the handlers made thread safe?

What may be session specific info
-Task context, tree logged in, user logged in, server logged in, browser info
These can be handled by a SessionHandler which creates a SessionBean.
SessionHandler should be called by dev.Task.

Obviously, state is maintained in SessionBean by Handlers-Workers.

We make handlers thread safe by creating different sessions for different threads.

All the Workers will have a lot of common responsibility.
These should be part of a singleton Utils.
Design should ensure that everything in Utils is stateless.

Session Bean is visible to all handlers and workers, in plugin terms, it is the PanelInfo. Session bean removes global variables in classes in Application layer. It provides a way for session tracking.

Error handling
The worker handles the error and abstracts as WorkCannotBePerformed
Handler handles the error and abstracts as RequestCannotBeHandled
Pagehandler further abstracts the error as PageSubmissionCannotBeHandled
dev.Task further abstracts as TaskExecutionFailed

So, we do not see a NullPointerException, but which action in which page by what task caused the null pointer exception.

This is the Exception pattern

Thus the generic design applies
Chain of responsibility
SessionFacade
Exception
Singleton

patterns

A session in a plugin is different from HttpSession. Every invocation of task may start a new session. This may be from same browser/client.

Hence SessionBean needs some identification for this task's session.

Every JSP page has 3 hidden parameters:

  1. pageid
  2. actionid
  3. sessionid

This should be present in every request, response of task.

Instead of making servlets get created for every request, all state information should be stored in Session Bean.

I am presenting a DeleteContainer task, which uses this generic design:


All handlers are singletons, never 2 instances of any handler is created.
Workers can run in threads, so that handler does not hang.

All workers are stateless; all state information is passed in SessionBean which is not shown.



Informacja z serwisu http://www.djack.com.pl