Coding standards

SUMS architecture

View

Facelets

Controller

Managed beans

Business operations

Service classes

Entity classes

One class per entity type

Facades

One facade per entity type

Database

 

Components, names and standards

Component Location Naming convention Notes
View: facelets /WEB-INF/view/module viewname.xhtml

Must follow the standard template (to be defined)

Each view should display a particular view of business data (coupled with errors and other messages as appropriate). Where there is a common fragment of two or more pages, the fragment should be implemented as a JSF component (as appropriate).

All input items on forms MUST have a validation rule set.

Ajax may be used as appropriate to make a view more dynamic.

Controller: managed beans jim.sums.module.ctrl

EntityController

or

BusinessFunctionController

Normally, one controller for each major entity class being managed.

Must extend AbstractController or a class derived from it. Will normally be @RequestScoped. Jim must OK any other scope.

Each managed bean action must:

  1. Ensure that input has been validated and invoke an appropriate view (usually the original view) if validation fails.
  2. Only if validation succeeds, call one or more business functions from one or more service classes. (The managed bean must obtain any needed service via EJB injection.)
  3. Catch BusinessExceptions raised by service classes and produce appropriate error messages in an appropriate view.
  4. If the business functions all succeed, return the correct string to JSF that wil invoke an appropriate view.
Model: business operations (services) jim.sums.module.bus ModuleService

If there are lot of business functions in a module, they may be broken up into separate service classes with appropriate names indicating the group of functions they hold.

There should be a separate service class for each Stateful EJB (i.e. one that is strictly necessary for a multi-stage process). Jim's OK must be given before creating one of these.

Must extend AbstractService or a class derived from it. Will normally be @Stateless EJB. Jim must OK any other annotation.

Each service method must:

  1. Ensure that all data input to it has undergone appropriate verification (e.g. that all referenced data exists)
  2. That the user has appropriate authorisation to perform the action on the specific data
  3. Service class methods must throw jim.BusinessException whenever they are unable to successfully complete their function. The lower-level exception that caused the error should be attached as the cause parameter to the BusinessException.
  4. Perform the business function, ensuring that all relevant data is updated, created or deleted as appropriate. The managed bean must obtain any needed sub-service or facade via EJB injection.
Model: entity classes jim.sums.db Entity

Class names must be accurate labels for the entity they represent. Almost always, the name will be singular unless the class only represents a collection.

Must implement Serializable.

Entity classes may be freely used throughout facade, service and managed bean classes, as well as in facelets that form the view.

Model: data access facades jim.sums.facades EntityFacade

One per entity class that is persisted to the database. This class should be created (if it does not already exist) when implementation of higher-level functions requires objects of the entity class to be persisted.

Must extend AbstractFacade or a class derived from it.

The AbstractFacade class implements a number of commonly used operations including a find method, save and delete. Since all objects returned by a facade are in the persistent state, there is no need to perform any sort of update operation on them. Newly created objects that should be stored in the database should have create called on them.

Some facade classes might not provide any further methods beyond those provided by the base facade class. However, if additional database operation methods are required (e.g. find objects by some complex condition), they should be implemented here.

All methods that fetch objects from the database should have names of the form findByCondition. They should have one or more parameters as required to pass details of the condition. Normally, implementation will be by means of a JPAQL query, though query by example or criterion is permitted.

Note that any find operation that returns either a single object of type Entity or a collection/set/list of items of type Entity, should be implemented in the class EntityFacade. This is the case even if the find operation has parameters of other types.

Coding style guide

Problem Solution
Writing a service method to check some attribute of an entity If the method will clearly be of value of other uses of the same entity, write it as a method in the entity class instead