Mai Architecture

MAI Architecture addresses many of the areas commonly required for bespoke applications.

Most importantly it achieves the seperation of business logic from the front end development by providing default front ends which are dynamically rendered depending on the user permissions. This means that unless a bespoke front end is required, ALL the development is on coding the business requirements.

Order Example

We take an order process as an example.
Client user accounts. Depending on who you are, you have differnt access to orders, or stock information.
All field access is permission driven. All fields ( e.g. order date ) may be visible, or editable depending on who you are.
All reports are permission driven. You have access to different reports e.g. give me all the orders yesterday.
Standardised workflow and workflow steps. There is just one screen for processing orders, taking invoice payments or any other work process you have to perform.
All workflow steps permission driven. Who you are dictates what you can do to the orders.
All actions can be applied to objects in bulk. This means if your desired action is to send a bulk email to all orders taken yeserday , you can just open the order report, and perform the bulk email action on all the orders.
Reports are linked to objects Your order report allows you to DO THINGs on the orders.
Default GUIs For new applications, only the objects, actions and workflows have to be coded. The JAVA SWING application, as well as the Struts MAI Arch module will render the default front end automatically.

 


MAI Arch

 

Mai Arch is short for Mai TechnologyArchitecture. It is the application framework developed and used by Mai Technology.

 

The framework provices for a set of object independent components which negate the need for initial front end development.

 

Provided business objects are coded according to these guidelines then the MaiArch gui components and struts components with handle them correctly.

Beans

 

Beans representing business objects implement the MaiArch.j2ee.EntityBean interface. See appendix A for the interface listing.

 

This interface corresponds closely with the j2ee standard Entity Bean interface.

 

Optional Methods

Optional methods are methods which are searched for in a bean by various components of TrackII but which are optional. They are not enforced through an interface, but instead the calling objects will search for them with introspection.

 

public static StockItem ejbFindByPrimaryKey(String primarykey) throws Exception

Instantiates the specified bean. Throws and exception if the bean cannot be found in the database.

 

public static final String[] getVectorsToExpand()

Returns a string array of vectors which should be expanded on the BeanDisplayPanel. If a vector is not in this list but has a get / set method pair then the vector is simply displayed in the bean display panel with its name and item count. The user can drill down into this vector using the F1 key, at which point the vector is opened in a BeanVectorPanel. If the vector is in this list then the BeanVectorPanel is created and added to the BeanDisplayPanel so that it is all viewed on 1 screen.

 

e.g. in StockItem

 

public static final String[] getVectorsToExpand (){

    return new String[] {"vectSubItems"};

    }

 

public static final String[] getQuickLookup()

Beans are searched for using a standard search panel BeanLookupPanel which looks at the primary table for the bean and allows searching whilst limiting the number of records returned from the table. The returned string array should consist of 3 fields,

the primary table, the primary field which is used by ejbFindByPrimaryKey and any additional fields which should be shown during the search.

 

e.g. in StockItem

 

  //returns table information for quick lookups

  public static final String[] getQuickLookup()

    {return new String[] { "tblSKU", "txtID", "txtDescription,txtCategory" };

    }

 

public Vector getTables()

Returns a vector of strings listing the primary tables for this bean. The user can then view the tables directly. This table access is through the bean display panel using CTRL T. This table list will expand with subclasses.

 

e.g. in StockItem

 

   public Vector getTables()

    {

    if(vectTables == null)

      {

      vectTables = new Vector(1,1);

      //add any constraints here in the future

      vectTables.addElement("tblCategory");

      }

    return vectTables;

    }

 

e.g the Memory bean which is subclassed from StockItem

 

   public Vector getTables()

    {

    if(vectTables != null)

      return vectTables;

    super.getTables();

    //add any constraints here in the future

    vectTables.addElement("tblMemory");

    vectTables.addElement("tblMemoryType");

    return vectTables;

    }

 

 

public Vector getFieldConstraints()

The field constraints are listing of foreign keys for use in constrained fields. These constraints are used by the BeanDisplayPanel and BeanTable objects which display the constrained fields as drop down boxes and do not allow the user to type in their own values.

 

A field constraint is defined by the field of the object which it applies to, and a SQL string which returns a data pair of the value to be placed in a field and also the visible value for the drop down box.

 

e.g the StockItem bean

 

   public Vector getFieldConstraints()

    {

    if(vectFieldConstraints == null)

      {

      vectFieldConstraints = new Vector(1,1);

      try{vectFieldConstraints.addElement(new FieldConstraint("txtCategory",

          "SELECT txtCategory, txtDescription FROM tblCategory ORDER BY txtDescription"));

          }

       catch(Exception e)

          {MW.utils.HandleException (e,MW.App.errFileName , " Memory.getFieldConstraints");

          }

      }

    return vectFieldConstraints;

    }

 

SubClassed beans simply continue adding their constrained fields to the vectFieldConstraints.

 

e.g. the MemoryBean

  public Vector getFieldConstraints()

    {

    if(vectFieldConstraints != null)  //this has already been initialised so just return

      return vectFieldConstraints;

 

    super.getFieldConstraints();

    try{vectFieldConstraints.addElement(new FieldConstraint("txtType",

          "SELECT txtType, txtDescription FROM tblMemoryType"));

       }

    catch(Exception e)

      {MW.utils.HandleException (e,MW.App.errFileName , " Memory.getFieldConstraints");

      }

    return vectFieldConstraints;

    }

 

 

public static final String getDefaultWorkflow()

Returns the default workflow name for this object. The StatePanel will originally populate with the state history from this workflow.

If there is only one start state for this object then the Object will go through this state transition automatically.

 

    {return InternalRequestRaisingWorkflow.IR_RAISING;

    }


 

DatabaseAccess

 

Database access is performed through a global database connection held in MediaTools.System. This is configured at the startup of the program. Concurrency issues are not addressed through the beans. This means that many people can have access to the same business objects. Locking is performed through means of a lock table tblLock which is controlled through the BeanDisplayPanel and the BeanTable objects.

 

N.B. the global database access can be a connection pool.


Bean Actions

A Bean Action is an piece of functionality which operates on a bean. It is separated from the actual bean class itself as it may involve GUI action which would make it incompatible with the j2ee model.

 

A Bean Action class must have a class name like it’s target bean followed by ‘Action***’ where *** is the unique action name, and exist in the same package as the target bean. A Bean action class only has one target bean associated with it although once the action is started it can do anything with any number of beans.

 

For example the MediaTools.Contact.User class has and ActionClass called UserActionClonePermissions associated with it which acts upon it.

 

This naming is necessary because the MediaTools GUI looks for permissions with this name relationship when it is deciding what actions a user may perform on a bean.

 

Bean Actions implement the following interface which is in the MediaTools.Infrastructure package:

 

package MaiArch.Infrastructure;

 

public interface BeanAction {

  public String getDescription();

  public String getButtonDescription();

  public Object doAction(Object c,Object bean) throws Exception;

  public void repeatAction(Object c,Object bean) throws Exception;

  public void cleanup(Object c) throws Exception;

}

 

getDescription() and getButtonDescription() are used in the popup menus for selecting an action. doAction() is performed on an object if 1 object has been selected to have this action performed on it. repeatAction() is performed for all subsequent actions if more than 1 object has been selected to have this action performed on it.

 

It is possible to select more than 1 object both in the BeanTable and SQLTable classes. For example in the UserActionClonePermissions class doAction() requires the user to specify a source User bean. If this action is perfomed on many Users then repeatAction() uses same User for any subsequent permission cloning. – crap example – due to the fact it is on User – but the only one I can give at the mo!!

 

N.B. In essence this corresponds to the SessionBean of the j2ee model with the addition of GUI awareness.

 


Struts considerations

 

Actions which additionally inplement the struts bean action interface will appear in the permissions driven drop down many on the struts site. The interface is as follows

 

 

public interface  StrutsBeanAction {

 

  public ActionForward initialise(ActionMapping mapping,

            ActionForm form,

            HttpServletRequest request,

            HttpServletResponse response) throws Exception;

 

  public ActionForward process(ActionMapping mapping,

            ActionForm form,

            HttpServletRequest request,

            HttpServletResponse response) throws Exception;

 

}

 

 

The initialise action is expected to initialise the actionparamters vector in the formEntityBean e.g.

 

FormEntityBean fm = (FormEntityBean) form;

               Vector vActionParameters = new Vector(2,2);

               for(int i = 0; i < strutsParams.length; i++)

                {vActionParameters.addElement(new KeyValue(“emailText”,

                                                           “defaultValue”));

 

 

These parameters are rendered with input controls on the action process page. The  public ActionForward process method then retrieves the ActionParameters to continue with the action.


 

Workflows

 


 

 

Permissions

 

All permissions are defined through the ObjectPermission class whose primary data is held in tblObjectPermission.

 

The object permissions are defined on a per user basis. Each User has a parent User object. The object permissions are first inherited from the parent user, and then overridden by the users own permission. In this way a user’s permissions may be more than their parent’s permission or less than their parents. In addition there is a UserLevel defined for each user. These User Levels are uses to set certain options for the user. For example an IT level user automatically creates new ObjectPermission objects if they are not defined with full access to the system, whereas if any other user is looking for an ObjectPermission which is not defined it is created with no access which then has to be edited by a user with permissions to edit them.

 

The ObjectPermissions affect the following areas of the front end screens:

 

Field Visibility

The field visibility sets the visibility of the field exposed by the specified method for both BeanDisplayPanel and BeanTable.

 

tblObjectPermission

Field

Value

Example

txtClass

The Bean Class

MediaTools.Stock.CPU

txtField

The Access Method

setTxtWebCopy

 

 

Utility Menu Visibility

All elements of the Utility menu are set with entries in the tblObjectPermission.

These fields are accessed in the buildUtilityMenu method of MediaTools.Applications.Admin. Default menu options do not have permissions set in this way but are visible to all users.

 

tblObjectPermission

Field

Value

Example

txtClass

MaiArch.Infrastructure.Utility

MediaTools.Infrastructure.Utility

txtField

Classname

DBSwingPanels.UrlRequestPanel

 

 


Object Action Permission

Defines which users are permitted to perform which actions on an object.

 

TblObjectPermission

Field

Value

Example

txtClass

The Bean Class

MediaTools.State.User

txtField

The Action Class

MediaTools.State.UserActionCascadePermissions

 

 

Report Permission

Defines which users are permitted to perform which reports.

 

TblObjectPermission

Field

Value

Example

txtClass

MediaTools.Report

MediaTools.Report

txtField

The Report file (*.mtr) or the report class

User.mtr

or

MIS.MISSalesByCustomer

 

 

State Transition Permission

Defines which users are permitted to use which state transition.

 

TblObjectPermission

Field

Value

Example

txtClass

MediaTools.State.StateTransition

MediaTools.State.StateTransition

txtField

The start and end state ID with -> in between

7->4

 

 


Appendices

 

Appendix A – Business Object Listing

 

package MaiArch.j2eestubs;

import java.util.Vector;

import MaiArch.State.User;

 

/**

* interface which corresponds to j2ee EntityBean interface

*/

public abstract interface EntityBean extends java.io.Serializable

{

 

  /**

   * The following methods correspond to the j2ee Entity Bean Interface

   */

  void setEntityContext(String p0) throws Exception;

  void unsetEntityContext() throws Exception;

  void ejbRemove() throws Exception;

  void ejbActivate() throws Exception;

  void ejbPassivate() throws Exception;

  void ejbLoad() throws Exception;

  void ejbStore() throws Exception;

 

  /**

  * The following method ensures that a string unique ID is available. This is used for

  * variouse GUI components in displaying the bean.

  */

  public String getTxtID();

  public void setTxtID(String txtID) throws Exception;

  public Vector getFieldConstraints(Integer GUIType,String sourceField);

  public void ejbRecreate(MaiArch.DataAccess dest) throws Exception;

 

  }



Comments on this site should be directed to: Your Comments


Copyright ©1998 Mai Technology Ltd Bodorgan House 26 Bodorgan Road Bournemouth BH2 6NL England
Tel: +00 44 776156878