Wandora modules framework

From WandoraWiki
(Difference between revisions)
Jump to: navigation, search
(Module dependency solving)
(Writing new modules)
Line 73: Line 73:
  
 
== Writing new modules ==
 
== Writing new modules ==
 +
 +
=== Module hierarchy ===
  
 
You can make your own modules by implementing the ''Module'' interface or extending one of the abstract classes partially implementing it. Obviously you will need extend a higher level class or implement a certain interface if you wish to make your class do a specific task in the framework. All actions need to derive from ''AbstractAction'' but there are also higher level options like ''GenericTemplateAction''. In fact ''GenericTemplateAction'' can even work without any extension if you place the application specific code in the template itself. Below is a list of the most common extension points. More details of specific methods can be found in the javadoc.
 
You can make your own modules by implementing the ''Module'' interface or extending one of the abstract classes partially implementing it. Obviously you will need extend a higher level class or implement a certain interface if you wish to make your class do a specific task in the framework. All actions need to derive from ''AbstractAction'' but there are also higher level options like ''GenericTemplateAction''. In fact ''GenericTemplateAction'' can even work without any extension if you place the application specific code in the template itself. Below is a list of the most common extension points. More details of specific methods can be found in the javadoc.
Line 90: Line 92:
 
* GenericTemplateAction
 
* GenericTemplateAction
 
: This is a direct extension of CachedAction and adds template handling. This class doesn't have any abstract methods and is useful on its own without any extensions. It will take an http request, use the template specified in the config with the context also specified in the config and then return the result of running the template through the template engine. If you only require minimal application logic which can be placed in the template, then you can just use this class directly instead of extending it. Otherwise extend the class and add some application logic and then add more things in the context if needed.
 
: This is a direct extension of CachedAction and adds template handling. This class doesn't have any abstract methods and is useful on its own without any extensions. It will take an http request, use the template specified in the config with the context also specified in the config and then return the result of running the template through the template engine. If you only require minimal application logic which can be placed in the template, then you can just use this class directly instead of extending it. Otherwise extend the class and add some application logic and then add more things in the context if needed.
 +
 +
=== Module life-cycle ===

Revision as of 12:17, 21 March 2014

Wandora contains a modular framework for setting up server applications. This can be used as part of a standard web app, or as a basis for a custom server application. It can also be used in the Embedded HTTP server. It could be used for other purposes than just server applications too but that is its primary purpose.

Contents

Introduction

The idea behind the framework is that the server application consists of several individual modules, each of which does one specific thing. The modules often have dependencies between them, but some may also perform a completely isolated task.

As an example, a typical application might consist of the following modules:

  • A topic map manager that provides a topic map for other modules and handles things related to the topic map.
  • An Apache Velocity engine module which handles interfacing with Velocity.
  • A template manager module which handles common tasks related to page templates.
  • Several template modules, each representing one page template. These will register themselves to the template manager so other modules can find them, and use the Velocity Engine module to render the page. The templates could also be other than Velocity templates, but currently Velocity is the only supported template engine.
  • A server module that receives HTTP requests and forwards them to other modules. Currently there are two options for this. One which interfaces a standard servlet container, such as Apache Tomcat, and one which interfaces with the Embedded HTTP server.
  • Several action modules, these are the logical entry points for outside users. They receive the requests from the server module and then process them. The action possibly does something on the server side and then gives back a result, typically by utilising one of the templates. Some of the action modules may utilise the topic map manager module to do something with the topic map it provides.

There are several other modules that an application could also utilise. Some examples are a database module which connects to a relational database, a module that sends email, modules that restrict access based on user authentication, and others.

Many of the modules work behind abstract interfaces with the idea that the implementation of a required module can easily be changed. The above list of modules already mentioned one such example: the two different options for the server module. Some others have been defined with an interface but currently there is only one implementation, like the templates. They could use any templating engine but currently Apache Velocity is the only supported one.

Example web app

Configuration file

Basic structure

All the modules are defined in a configuration file, typically called modulesconfig.xml. This is an XML file with a fairly simple structure. The root element is <options> and under it each module is listed in <module> elements. The <module> element contains the Java class name of the module, which must implement the Module interface. Parameters for the module can be provided as child elements of the <module> element in <param> elements. For example, the following includes two modules, with the latter one containing some initialisation parameters for the module.

<?xml version="1.0" encoding="UTF-8"?>
<options>
  <module class="org.wandora.modules.LoggingModule"></module>

  <module class="org.wandora.modules.topicmap.SimpleTopicMapManager">
    <param key="topicMap">topicmap.wpr</param>
    <param key="autoSave">true</param>
  </module>    
</options>

Module dependency solving

Some module may require other modules to be present. All the required modules must be included in the config file. Their order does not matter, the modules are automatically loaded in such an order that modules that require others are loaded after the modules they need. This also means that there cannot be cyclic dependencies between the modules, although there are ways to work around this.

Dependencies are solved automatically based on the required module class or interface. The config file just needs to contain a module of that class or one implementing, or extending, it. But in some cases there may be more than one valid option for the dependency and you need to specify which to use. There are two ways to solve this.

First, you may name modules and then explicitly specify which module to use. Specify the name of the module in a name attribute in the <module> element. Then in the module that needs to use the other module, add a child element <useService> which specifies the service. Like this:

<module class="org.wandora.modules.topicmap.SimpleTopicMapManager" name="tmmanager">
  <param key="topicMap">topicmap.wpr</param>
  <param key="autoSave">true</param>
</module>    
<module class="org.wandora.modules.topicmap.ViewTopicAction">
  <useService service="org.wandora.modules.topicmap.TopicMapManager" value="tmmanager"></useService>
  <param key="action">topic</param>
  <param key="templateKey">viewtopic</param>
</module>

In the service attribute you must specify which service this relates to and then in the value attribute you specify the name of the module to use.

The second option to resolve the conflict is to specify a priority for the modules. You do this with a priority attribute in the <module> element. Each module by default has priority 0. A module with a higher priority will be chosen over a module with a lower priority in the automatic dependency solving. A module with a negative priority will never be automatically used, it can only be used by explicitly specifying so with the <useService> element as shown above. The <useService> will always override any priorities.

In the following example, the second topic map manager would not automatically be chosen for other modules. If any module wishes to use that, it must be explicitly specified with the <useService> element as shown above.

<module class="org.wandora.modules.topicmap.SimpleTopicMapManager">
  <param key="topicMap">topicmap1.wpr</param>
  <param key="autoSave">true</param>
</module>    
<module class="org.wandora.modules.topicmap.SimpleTopicMapManager" priority="-1">
  <param key="topicMap">topicmap2.wpr</param>
</module>

Also, the modules themselves may employ other means to specify what to use. As an example, all Template modules register themselves to a TemplateManager. Modules which need templates then don't depend directly on the Template module but instead on the TemplateManager which has its own mechanisms for getting the correct Template module.

List of modules

Writing new modules

Module hierarchy

You can make your own modules by implementing the Module interface or extending one of the abstract classes partially implementing it. Obviously you will need extend a higher level class or implement a certain interface if you wish to make your class do a specific task in the framework. All actions need to derive from AbstractAction but there are also higher level options like GenericTemplateAction. In fact GenericTemplateAction can even work without any extension if you place the application specific code in the template itself. Below is a list of the most common extension points. More details of specific methods can be found in the javadoc.

  • Module
The root interface of the module class hierarchy. This is the most generic option available. But in most cases you should instead extend the AbstractAction instead which has basic implementations of all the methods.
  • AbstractModule
This is the most generic of the abstract classes implementing Module. All methods of the Module interface are implemented, but they don't really do anything useful without overriding some methods or adding functionality in other ways.
  • ScriptModule
This is a direct extension of AbstractModule which provides some scripting features in the modulesconfig.xml file for the module. Modules deriving from this can have scripts specified in the config which are ran when the module is initialised, stopped or started. You may want derive your class from this instead of AbstractModule to get these features, even if you don't immediately plan to use them. They can later be used to add triggers when a module is started or stopped.
  • ServletModule.RequestListener
This is the interface for action classes that respond to http requests.
  • AbstractAction
This is an abstract class that implements the ServletModule.RequestListener interface and can thus respond to http requests. It also extends ScriptModule, and thus AbstractModule, so it has basic module implementation as well. This is basically the most generic abstract class to extend for action type modules.
  • CachedAction
This is a direct extension of AbstractAction and provides caching options for the action. If your action can benefit from having action results cached, you should consider extending this action. Caching can always be also turned off in the config even if you do extend from this class.
  • GenericTemplateAction
This is a direct extension of CachedAction and adds template handling. This class doesn't have any abstract methods and is useful on its own without any extensions. It will take an http request, use the template specified in the config with the context also specified in the config and then return the result of running the template through the template engine. If you only require minimal application logic which can be placed in the template, then you can just use this class directly instead of extending it. Otherwise extend the class and add some application logic and then add more things in the context if needed.

Module life-cycle

Personal tools