Table of Contents

Modularity

TODO: Introduction

Backend

After discussing the topic, Spring Plugin was chosen as a framework for ensuring backend modularity. Compared to other considered frameworks such as OSGi or Microservices, it is the simplest option based on interfaces, their implementations and registration of these implementations for their use in the application. The accepted disadvantage is application server restart after installing a module (module = .jar package).

Installation/ module update

Installation/ module update is done by copying the module into the application libraries <idm.war>/WEB-INF/lib. Modules can also be included directly in the project dependencies (pom.xml modul app).

Module descriptor - ModuleDescriptor

Each module installed in the application must have its descriptor - ModuleDescriptor. The descriptor contains the metadata about the module:

All modules - their descriptors - are registered at the start of the application and can be managed through service ModuleService providing mainly:

* the list of installed modules * the list of permitted modules * enabling/ disabling of the module - linked to configuration service IdmConfigurationService. By convention, item idm.pub.<identifikátor_modulu>.enabled is used for determining of an enabled / disabled module. This item gains boolean value.

Database scripts

Each module can contain its own database scripts.

Example module

The example module was created for module demonstration and, at the same time, as a template (skeleton) for creating a module with pre-filled configurations. It contains:

* pom.xml - dependency settings * module descriptor - descriptor * flyway configuration - for db initialization

If the example is used for creating a new module, the key word example has to be replaced with another unique module identifier and then various descriptions (module name, description, etc.) can be added. For future uses, it is planned to create a maven archetype or other module skeleton generator.

Enabling / disabling of module

An agenda which shows the list of installed modules and enables enabling / disabling of modules which support this function (see descriptor) was created on the frontend.

After disabling of a module, all the services (e.g. rest) must become unavailable. This is done by annotation IfEnabled, which, after adding it over a service or an individual method (definition over a service has a higher priority), ensures a control over the enabled module or configuration item before calling a service / method itself. Calling a service of a disabled module ends in exception ModuleDisabledException or rather ConfigurationDisabledException.

If a frontend module is linked to / dependent on a backend module, it is also disabled.

TODO:

* checking of module id uniqueness at the start of application * maven archetype for generating the module skeleton

Frontend

The goal of frontend modularity was to fulfill the following scenario:

  1. A standard version of CzechIdM (e.g. 7.0) is installed on the frontend server.
  2. The administrator downloads a czechidm (npm) module, which he loads in folder czechidm-modules (in module czechidm-app).
  3. The administrator runs a compilation (command gulp build see more in the installation manual )
  4. By doing that, a new module was registered in the application and its content is displayed to the user in the application (including integration of individual menus, user desktops, etc.)

Application building

Building of a frontend application including its modules is done by the Gulp building tool. The definition of the building process is save in file gulpfile.babel.js. This file contains a series of tasks which are run in a fixed order during building:

Project structure

Below is the structure of the project and its modules. The folder containing all npm modules "node\_modules" (in the main module czechidm-app) is designed as a symlink. Its actual location is one level higher which was necessary to prevent an error with more copies of ReactJS (see https://facebook.github.io/react/warnings/refs-must-have-owner.html).

This error occurs in a situation when one installation of the React npm module is in 'czechidm-app/node\_modules' and the other in its submodule 'czechidm-app/node\_modules/czechidm-core/node\_modules'. In this case the error described above occurs.

A solution is to remove the duplicate installation from React from the submodule. If this submodule isn't really located under the file czechidm-app but for example next to it (in reality, it is in this way in the repository), then czechidm-core will find no installation of React. The reason is that NPM looks for modules in node\_modules and if it doesn't find them, it moves on to a higher level recursively. Because of that, the main node\_modules folder is (and must be) located above all czechidm modules (app, core, acc, etc.)

/project
└───node_modules
|    |
|    └───~czechidm-core (symlink to czechidm-modules/czechidm-core)
|    |
|    └───~czechidm-example (symlink to czechidm-modules/czechidm-example)
|
└───czechidm-app
|    |
|    └───~node_modules (symlink to parent node_modules)
|    |
|    └───dist (final compiled source for web server)
|    |
|    └───czechidm-modules
|        └───czechidm-core
|        |    |
|        |    └───node_modules
|        |    |
|        |    └───src
|        |    |    |
|        |    |    └───css
|        |    |    |  main.less
|        |    |    |
|        |    |    └───locales
|        |    |       cs.json
|        |    |
|        |    └───themes
|        |    |  module_descriptor.js
|        |    |  routes.js
|        |    |  component_descriptor.js
|        |    |  package.json
|        |    
|        └───czechidm-example
|        |    |
|        |    └───node_modules
|...          ...

Project structure (developer mode)

The structure is almost the same as in the previous "production" example. The difference is in the location of submodules, which aren't under the 'czechidm-app' folder but next to it (real location in the repository). Symlinks to these submodules are placed in 'czechidm-app/czechidm-modules/' for that reason.

/project
└───node_modules
|    |
|    └───~czechidm-core (symlink to czechidm-modules/czechidm-core)
|    |
|    └───~czechidm-example (symlink to czechidm-modules/czechidm-example)
|
└───czechidm-app
|    |
|    └───~node_modules (symlink to parent node_modules)
|    |
|    └───dist (final compiled source for web server)
|    |
|    └───czechidm-modules
|        |
|        └───~czechidm-core (symlink to folder with czechidm-core module)
|        |
|        └───~czechidm-example (symlink to folder with czechidm-example module)
|
└───czechidm-core
|    |
|    └───node_modules
|    |
|    └───src
|    |    |
|    |    └───css
|    |    |  main.less
|    |    |
|    |    └───locales
|    |       cs.json
|    |
|    └───themes
|    |  module_descriptor.js
|    |  routes.js
|    |  component_descriptor.js
|    |  package.json
|    
└───czechidm-example
|    |
|    └───node_modules
....