Before you read this example, it is highly recommended that you read "Introduction to Kilim Configuration Files (KCFs)". It is assumed that the reader is familiar with the concepts of bootstrap and runtime kcf
s.
The goal of this tutorial is to present the various Kilim concepts in a hands-on, no-nonsense way, through building and configuring an example.
The example chosen here is a web application acting as a classical web log. The purpose of this application is to add and display some text entries. This example will, hopefully, demonstrate the intrinsic power of Kilim as well as its better side-effects such as making the application architecture more explicit.
At the heart of WebLog is a servlet, called WebLog with a lot of originality. This servlet is to be deployed under Tomcat 4.0.3. The servlet will first only read some text and print it on screen. The reading backend is separate.
Optional functionalities will be added through this tutorial, such as several kinds of data storage (non-persistent, persistent via flat files or a database), an authentication module, as well as extending the functionality.
Note:
All WebLog 1.0 files are available for download.
In this example we want to take advantage from the dynamic aspects of Kilim, so WebLog uses two Kilim Configuration Files: a bootstrap kcf (Startup.kcf
) and a runtime kcf (runtime.kcf
).
Here is our bootstrap kcf (Startup.kcf
).
<?xml version="1.0" encoding='ISO-8859-1'?> <!DOCTYPE Configuration SYSTEM "configuration.dtd"> <CONFIGURATION bootstrap="org.objectweb.jonathan.libs.kernel.helpers.Kernel" generated="weblog.Startup"> <ELEM name="runtime configuration file"> <PROPERTY type="String" value="weblog.kcf"/> </ELEM> </CONFIGURATION> |
Here is our runtime kcf: weblog.kcf
.
In this kcf, one can see two major constructs: an ATOM
and an ASSEMBALGE
. In the Kilim terminology, these represent the two ways to specify an object instance.
ATOM
s are the simplest manner to get a handle on an object instance. The DTD specifies that ATOM
elements have a compulsory class
attribute. Upon encountering such an element, the Kilim runtime will try to instantiate the given class by using a default constructor (that is, a constructor without parameters).ASSEMBLAGE
s represent a more subtle way to create object instances. They work on the principle of the Factory design pattern: object instantiation is delegated to a specialized construct, the FACTORY
. In Kilim, ASSEMBLAGE
s may have a specific CONFIGURATION
, the elements thereof are fed to the given FACTORY
to specify how to instantiate the object.FACTORY
can be anything: IMPLICIT_FACTORY
, ATOM
, or even ASSEMBLAGE
. Of course, it can also be an ALIAS
to a proper FACTORY
(more on ALIAS
es later).
ATOM
or explicit factory. The class this atom represents needs to implement org.objectweb.jonathan.apis.Factory
. This interface only defines one method: Object newObject(Context c);
. The Context
provided by the Kilim runtime is the ASSEMBLAGE
's CONFIGURATION
.IMPLICIT_FACTORY
. This simply represents construction via the use of abitrary constructors and setter methods. The IMPLICIT_FACTORY
allows defining multiple (numbered) alternatives, corresponding to, e.g. several constructors for a class, or even for several classes. In the coming paragraphs we will use implicit factories and alternatives.For more information, please check the Kilim configuration DTD.
Back to our example. The servlet accesses the configuration by getting the Log Handler element defined through the use of an ASSEMBLAGE
element.
In the example, the factory is an IMPLICIT_FACTORY
. As we mentioned earlier on, an IMPLICIT_FACTORY
is made of ALTERNATIVE
(s), each ALTERNATIVE
is identified by its ID.
The alternative
attribute of the ASSEMBLAGE
element is set to "0", that means that at runtime, the assemblage will be created using the ALTERNATIVE
for which the id
attribute is "0".
With the ALTERNATIVE
's class
attribute and the ARGUMENT
s sub-elements, Kilim is able to retrieve the class and the constructor it needs to instantiate the object.
The required parameters are provided by the ASSEMBLAGE
's configuration (MY_CONFIGURATION
), and identified by their names.
Implicit factory description: |
---|
... <IMPLICIT_FACTORY> <ALTERNATIVE id="0" name="log handler" class="weblog.LogHandler"> <ARGUMENT type="weblog.business.apis.EntriesReader" name="entries reader"/> </ALTERNATIVE> </IMPLICIT_FACTORY> ... |
Assemblage description: |
---|
... <ASSEMBLAGE alternative="0"> <MY_FACTORY> ... </MY_FACTORY> <MY_CONFIGURATION> <CONFIGURATION> <ELEM name="entries reader"> ... </ELEM> </CONFIGURATION> </MY_CONFIGURATION> </ASSEMBLAGE> ... |
Note how the entries reader
element in the assemblage's configuration matches the factory's argument.
It is not necessarily such a great idea to define in an ad hoc manner an ASSEMBLAGE
's factory and configuration. Indeed, if one wants a component to be shared among two or more assemblages, we need a proper referencing semantic.
In Kilim, component crossreferencing is done through the use of ALIAS
es. An ALIAS
is simply a symbolic link to an arbitrarily placed element in the configuration; much in the manner similar constructs in filesystems (soft links, shortcuts, aliases, depending on your system of choice).
ALIAS
constructs are also useful when striving to have a simpler, more readable structure for your kcf
s since they help keeping the number of nesting levels down.
In our case, we use an ALIAS
in the previously defined ASSEMBLAGE
's configuration, to reference the entries reader we decide to use:
... <ELEM name="entries reader"> <ALIAS name="/Entries/memory entries reader"/> </ELEM> ... |
The ALIAS
points to another part of the kcf, namely:
... <ELEM name="Entries"> <CONFIGURATION> <ELEM name="memory entries reader"> <ATOM class="weblog.business.libs.MemoryEntriesReader"/> </ELEM> </CONFIGURATION> </ELEM> ... |
All WebLog 2.0 files are available for download.
From now, we want to add authentification to our weblog via a basic username / password scheme. Firstly we write the relevant class: weblog.business.libs.AuthenticationServiceImpl
, then we have to make it appear in the configuration.
To do this, we simply add an ATOM
to the runtime kcf (full version):
... <ELEM name="Authentication Service"> <ATOM class="weblog.business.libs.AuthenticationServiceImpl"/> </ELEM> ... |
The authentication service is very simple, since it does not require any parameter, it is defined by an ATOM
.
In order to allow the use of WebLog without authentication, the servlet looks for an object named Authentication Service in the configuration. If none is found, then no authentication is expected from the user.
This behaviour is coded in the servlet's source:
... Object $oAuth = initialContext.getValue("Authentication Service", (char)0); if ($oAuth != Context.NO_VALUE) { auth = (AuthenticationService)$oAuth; } ... if (auth != null) { ... } |
All WebLog 3.0 files are available for download.
In this version, we would like to specify a level for each new weblog entry. Therefore, we add another ALTERNATIVE
in our ASSEMBLAGE
. This ALTERNATIVE
needs an array of java.lang.String
for second parameter.
... <ALTERNATIVE id="1" name="log handler" class="weblog.LogHandler"> <ARGUMENT type="weblog.business.apis.EntriesReader" name="entries reader"/> <ARGUMENT type="java.lang.String[]" name="priority levels"/> </ALTERNATIVE> ... |
Then, we set the ASSEMBLAGE
's alternative
attribute to "1".
In Kilim, arrays are represented by SEQUENCE
s (full version):
... <ELEM name="priority levels"> <SEQUENCE elements_type="String"> <ELEM name="0"><PROPERTY type="String" value="Low"/></ELEM> <ELEM name="1"><PROPERTY type="String" value="Normal"/></ELEM> <ELEM name="2"><PROPERTY type="String" value="High"/></ELEM> <ELEM name="3"><PROPERTY type="String" value="Very High"/></ELEM> </SEQUENCE> </ELEM> ... |
All WebLog 4.0 files are available for download.
We mentioned in part one that implicit factories' ALTERNATIVE
s could use setter methods as well as constructors. Now we will take advantage of this example.
Note: in Kilim a setter method is defined as any method with only one parameter.
We would like to add the date in front of each entry. The LogHandler
class is modified to use a default date pattern which can be changed by invoking the setDatePattern
method with a String
parameter.
Another ALTERNATIVE
is added to the WebLog runtime kcf (full version):
... <ALTERNATIVE id="2" name="log handler" class="weblog.LogHandler"> <ARGUMENT type="weblog.business.apis.EntriesReader" name="entries reader"/> <ARGUMENT type="java.lang.String[]" name="priority levels"/> <SETTER name="setDatePattern"><ARGUMENT type="java.lang.String" name="pattern"/></SETTER> </ALTERNATIVE> ... |
The new parameter appears as a PROPERTY
in the configuration:
... <ELEM name="pattern"><PROPERTY type="String" value="MMM dd HH:mm:ss"/></ELEM> ... |
(Note: the pattern syntax is specified in the java.text.SimpleDateFormat
API).
Then, the alternative
's attribute of the ASSEMBLAGE
is set to "2".
Modify the runtime kcf (weblog.kcf
) in order to use a flat file data storage (weblog.business.libs.FlatFileEntriesReader
class).
Here is the solution: weblog.kcf
.
Last updated: 2002-09-10