Demeter
The Demeter project is founded based on the following requirements:
- Modular architecture with well-defined integration
- Each module has its own entities, services, and web parts
- A base container with all common and important services for all modules
- For deployment, a combination of modules can be deployed
- Common test cases can be executed for the container and the modules
So the Demeter project is:
- A container that finds its modules, called
DModule, in deployment and initializes them based on the lifecycle, even the deployment, itself, is a separate module - Provides base services for all modules, which are
PersonandUserManagementRole,Privileges, andSecurityManagement, and the integration with web- Background and Scheduled
Tasks, and pushing data back to web viaWebSocket File StoreManagement- Layout, Menu and Page Management for web
- Object
CacheManagement and UI for clearing them - Show the list of defined
configkeys, and modify them at runtime
- Define conventions and standards for modules.
- Define a convenient platform and ecosystem for faster
development,test, anddeployment - For generality, the Demeter, itself, has its own
DModule
Architecture
The architecture of Demeter and a DModule is presented in the following logical component diagram:
In the architecture, the Demeter project is composed of four maven jar artifacts:
Common: It has all the common and necessary classes and files which are shared between modules. They are- Entities: List of entities in DModule
- Value Objects: Based on value object pattern, they are classes that are used for data transfer
- Service Interfaces: The Spring beans' interfaces
- Privileges: A privilege is defined by
IPrivilegeKey. For the list of privileges, an enum is defined which implements theIPrivilegeKeyinterface. So the enum has all the privilege keys. - Config Keys: There is only one
config.propertiesfile for the development or deployment. So each module can have its own config keys in the file. Each config entry isIConfigKey, so an enum implements theIConfigKeyinterface, and the enum has all the config keys for DModule. - SQL Files: Since each module has its own entities, it must have its own SQL change scripts that handle schema modification carefully.
Service: It implements all the service interfaces defined inCommonartifact and whatever is necessary for the service tier.Core: Its main classDemeterCoreis responsible for all the lifecycle of Demeter and the deployed DModules.Web:- As Demeter, it has Wicket's
WebApplicationclass and all the necessary classes for handling web-side UI, and callingDemeterCore.init() - As a DModule, it has all the
DPagesand panels for its pages, forms, and lists.
- As Demeter, it has Wicket's
Module:- Each DModule has an XML config file with all necessary information. This config file will be described later.
- This artifact has direct dependencies to
ServiceandWebwith indirect one toCommon. So it can represent the DModule.
Startup Process
The DemeterCore class goes through the following steps for startup: 
XML Config Files
Each DModule has two XML config files. The first one is for Spring bean definition, which is located in the main/resoureces of Service maven artifact, and it is a standard Spring XML config file. Another one is DModule XML definition file, which is located in the main/resources/dmodule maven artifact. For simplicity, a summary of Demeter's DModule XML file is presented:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC
"Devocative/Demeter Module"
"http://www.devocative.org/dtd/demeter-module.dtd">
<module
shortName="DMT"
mainResource="org.devocative.demeter.web.DemeterDModule"
privilegeKeyClass="org.devocative.demeter.DemeterPrivilegeKey"
configKeyClass="org.devocative.demeter.DemeterConfigKey">
<entities>
<entity type="org.devocative.demeter.entity.DPageInfo"/>
<entity type="org.devocative.demeter.entity.DPageInstance"/>
...
</entities>
<tasks>
<task type="org.devocative.demeter.service.task.SimpleDTask"/>
<!-- Fire at 2:00 every day -->
<task type="org.devocative.demeter.service.task.FileStoreDTask" cronExpression="0 0 2 * * ?"/>
</tasks>
<dPages>
<dPage type="org.devocative.demeter.web.dpage.PersonListDPage"
title="KEY:dPage.dmt.Person"
uri="/persons"
inMenu="true"
roles="Admin" />
<dPage type="org.devocative.demeter.web.dpage.LoginDPage"
title="KEY:dPage.dmt.Login"
uri="/login"
inMenu="false" />
...
</dPages>
</module>
Environment
A convenient environment for development is very important. To reach the goal, one maven plugin and two archetypes are developed. The following picture tries to show all the components that are involved in this project. 
And finally, a simple screen from the Demeter 
How to Run
Running Demeter project is so simple. You can execute following commands:
git clone https://github.com/mbizhani/Demeter.git
cd Demeter
mvn clean install
cd module
mvn jetty:run
Now open your browser and go to this address: http://localhost:8080/ctx. The default config.properties uses the HSQLDB as the default database.
How to Create a DModule
As mentioned before, for convenience, a maven archetype is created to setup an initial DModule project. Besides, a maven plugin is used for generating simple CRUD for entities.
Note: the generated project from archetype has a simple Book entity as an example.
To create an initial DModule project:
mvn -B archetype:generate \
-DarchetypeGroupId=org.devocative \
-DarchetypeArtifactId=dmodule-archetype \
-DarchetypeVersion=1.0 \
-DgroupId=my.pkg \
-DartifactId=store \
-Dpackage=my.pkg.store \
-DModuleName=Store \
-DModuleShortName=STR \
-Dversion=1.0-SNAPSHOT
Now, by executing following steps, the CRUD classes and files are generated:
cd store
mvn clean install
cd module
mvn demeter:codegen
(Here, the codegen plugin finds data model added-changes and alerts on the screen. So the following will continue the procedure):
mvn demeter:codegen
cd ..
mvn clean install
cd module
mvn jetty:run
Calling mvn demeter:codegen the second time generates all the necessary classes and files. After installing the artifacts, in the module artifact calling mvn jetty:run will commence the Jetty web server and Demteter startup lifecycle. Now goto http://localhost:8080/ctx/books, which shows the generated list for Book entity. But before that, the login page is presented. The default username and password is:
| Username | Password |
|---|---|
| root | root |
How to Deploy
So far, a new DModule is created. It is time to deploy it as a WAR. Again, an archetype will come to help. The Deploy is a special DModule to package other DModules besides itself as a deployable WAR. Another advantage of this approach helps us to alter and define code for target deployment.
Note: As said before, the common DModule has four artifacts, however the Deploy DModule just has one artifact, which is the single WAR.
So, lets create a Deploy DModule:
mvn -B archetype:generate \
-DarchetypeGroupId=org.devocative \
-DarchetypeArtifactId=deploy-archetype \
-DarchetypeVersion=1.0 \
-DgroupId=my.pkg \
-DartifactId=store-dpl \
-Dpackage=my.pkg.store \
-DDeploymentTarget=Store\
-Dversion=1.0
The basis of deployment project is created. Its main pom.xml just has the dependency to demeter. Add the following dependency to dependencies section:
<dependency>
<groupId>my.pkg<groupId>
<artifactId>store-module<artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
To verify the result before deployment, execute mvn jetty:run and goto http://localhost:8080/ctx. To create the WAR, execute mvn package. If you have a running Tomcat, you can upload and deploy the WAR directly to it via maven tomcat7 plugin. Just execute mvn tomcat7:redeploy. The configs for tomcat can be altered in the <properties> of the pom.xml.
Projects
| Project | Homepage |
|---|---|
| Devolcano | https://github.com/mbizhani/Devolcano |
| DModuleArchetype | https://github.com/mbizhani/DModuleArchetype |
| DeployArchetype | https://github.com/mbizhani/DeployArchetype |