Modularisation
Why Modularize?
- Improved separation of concerns
- Learning code less steep for developers interested in a subset of the total functionality
- Enables different modules to depend on different versions of Java
- Allows development of experimental modules on trunk. This:
- Encourages alternative implementations
- Enables branching per module
- Simplifies multiple deployment targets
Modules Types
Dependencies between modules will be layered in the obvious way. For example:
http://svn.apache.org/repos/asf/james/server/sandbox/design-doodles/modules/dependencies.png
Build Modules
Contains code for James modular build
Deployment Modules
Contains code required to deploy James in various container environments
Function Modules
Factors out function from container specific implementations
Library Modules
Factor out common library code reused by functional modules into library modules
API Module
Single module containing the core James API
Execution
Stage One - Prerequisites And Preparation
Before code can be moved out from the phoenix deployment, some prerequisites need to be completed. This will allow the code moves to be planned whilst these are executed. Space needs to be created in the subversion tree by pushing the existing code base down a level. A lightweight ant build framework will be needed to allow efficient creation of modules.
[COMPLETE] Phase 1
Make space for modules within james server trunk
- server/trunk -> server/trunk/phoenix-deployment
[COMPLETE] Phase 2
Top level build
- create build.xml which delegates to phoenix-deployment/build.xml
[COMPLETE] Phase 3
Upgrade build:
- upgrade to ant 1.7 (the new features are *really* good)
- create stage subdirectory which is local only
- create buildtasks module to host build macros and ant tasks for
module builds
Phase 4
Create empty base module top to contain API interfaces
- create macros and tasks to support modular build
- create build-modules.xml to support common structure
- base builds copies artifacts into stage subdirectory
- phoenix build copies artifacts locally from stage
- create macros to allow easy generation of new modules
Stage Two - Factoring Code Into Modules
TBD
Recommendations:
- Try to avoid splitting packages between modules (good design and also plays well with modern packaging systems)
- This may mean that some repackaging is needed. Recommend that this is done in existing code (phoenix) before moving the code out into a module (easier to track code changes).
- Phoenix coupling should be factored out in the existing code (phoenix) before moving code out into a module (easier to track code changes)
Module Planning Proposals
Deployment
- phoenix-deployment: contains what we currently have in phoenix-bin and the necessary ant task to build our current binary distribution.
- spring-deployment
Function
- smtpserver
- pop3server
- fetchmail
- remotemanager
- nntpserver
- imapserver
- transport (maybe to be named spoolmanager)
- mailetcontainer: to contain the James.java and some of the transport/*loader* stuff.
Library
- usersrepository
- mailrepository
- mailboxmanager
- dnsserver
- vut
- domain
- management
API
Need to think about timing of mailet API move
Understanding The Modular Build
Master Build
Adopting some standard naming conventions allows the master build to automatically pick up all modules of a particular type. Subant can then be used to call the same target to all module build files of a particular type. This allows the modular build to automatically maintain the correct build order within needing to know about detailed relationships between modules.
Suggested conventions:
- Deployment modules - *deployment for example phoenix-deployment
- Function modules - *function for example smtp-function
- Library modules - *library for example user-repository-library
- API modules = *api for example james-core-api
Module Builds
Minimal Requirements
Deployment Modules
The minimum requirement is for modules to provide an ant build file which:
- provides standard targets:
- clean
- lite
- dist
- everything
Other Modules
The minimum requirement is for modules to provide an ant build file which:
- provides standard targets:
- dist
- clean
- creates artifacts in standard relative position
Standard Module Builds
To reduce maintenance, standard builds will be provided for modules that want to adopt a standard module layout.
Unresolved Issues
Logging
JAMES uses the Avalon framework for logging via AbstractLogEnabled. This introduces a deep coupling between the container and components running in the container that requires resolution.
First Cut User Components
user-api:
- JamesUsersRepository
- UsersRepository
- VirtualUserTableStore
- VirtualUserTable
- UsersStore
- User
- ErrorMappingException
domain-api:
user-library:
- JamesMBean
- VirtualUserTableManagement
- VirtualUserTableManagementService
- JamesUser
- DigestUtil
- DefaultVirtualUserTable
- LocalUsersRepository
- LocalJamesUsersRepository
- VirtualUserTableManagementException
- VirtualUserTableManagement
- UserManagementException
- UserManagement
- VirtualUserTableManagementMBean
- UserManagementMBean
- VirtualUserTableUtil
- XMLResources
- AbstractVirtualUserTable
- InvalidMappingException
- XMLVirtualUserTable
- UsersFileRepository
- UsersLDAPRepository
- DefaultUser
- DefaultJamesUser
- AbstractUsersRepository
avalon-user-function:
- AvalonUsersStore.java
- AbstractAvalonStore.java
- AvalonVirtualUserTableStore.java
jdbc-user-function: