This document describes the basic configuration of a Dwarf-based application. It covers the XML-based configuration feature of the Dwarf framework, as well as some of the framework's basic design principles.
Each server application includes one main server instance. Typically, it is an instance of the MainServer class. Let's include it in the XML configuration as the top-level service:
<configuration security="off" debug="tcp" trace="" verbose="off"> <!-- MAIN SERVER --> <service classbase="SK.gnome.dwarf." class=".main.MainServer" name="Main Server"> <set name="logFacility">main</set> <set name="authFacility">Dwarf</set> </service> </configuration>
The "logFacility" attribute specifies the string identifying the log messages generated by the server. This attribute is inherited by all nested services by default. However, any nested service may change this by setting ist "logFacility" attribute to a different value.
The second attribute "authFacility" specifies which login configuration will be used for the authentication. This attribute is also inherited by all nested services if they do not provide a different own value.
And that's all! We have just configured successfully the simplest server application.
Now, we should configure at least two more useful features - the logging and the authentication.
Logging in Dwarf works in a way that each call to one of the Service's logging methods is in effect propagated to the top-level main server. Here comes the build-in functionality of each server - if a service implementing the Logger interface (let's call it the logger) is inserted to a server, the server will divert all logging requests to the logger's log methods. The logger must thus implement these methods to perform the actual logging (i.e. writting the log events to a physical medium).
So what we should do now? Just find a suitable logger and add it to the main server object. One such a service implementing the Logger interface is the LogServer class:
<service classbase="SK.gnome.dwarf." class=".main.MainServer" name="Main Server"> <set name="logFacility">main</set> <set name="authFacility">Dwarf</set> <!-- LOG SERVER --> <service class=".log.LogServer" name="Log Server"> <set name="logFacility">log</set> <!-- SCREEN LOGGER --> <service class=".log.SystemLogger" name="Console Logger"> <set name="levels">info*</set> <set name="facilities">all</set> <set name="extendedInfo">true</set> <set name="dateTimeFormat">HH:mm:ss.SSS</set> <set name="markInterval">20</set> <set name="repeatedInterval">120</set> </service> </service> </service>
The LogServer is simply a container for other loggers. It routes the logging calls to all loggers it contains. As you can see we have configured and added just one particular logger - the SystemLogger. This service writes the log messages to the standard System.out stream, wherever this stream points to. (That's why we call it SystemLogger instead of ConsoleLogger, for example.)
Of course, it would be also possible to insert only the SystemLogger directly to the main server. But we would lose the great flexibilty of configuring many different loggers in one central place via the LogServer container.
All loggers in the SK.gnome.dwarf.log
package share some common useful attributes. The first one is the "levels"
attribute - it specifies which logging levels will be accepted by the logger.
The possible values are "trace", "debug",
"info", "warn", "error",
"fatal" or any combination of them. (See the LogLevel
class for more information on logging levels.) It is possible also to use a
wildcard character to specify all logging levels higher than the particular
level. For example, "info*" means that the logger will accept
levels "info", "warn", "error"
and "fatal". It is possible to use either a comma-separated
list of logging levels, or a single wildcarded level, not a combination of them.
The second common attribute is "facilities" - it specifies which logging facilities will be accepted by the logger. For example, if you specify the string "http", only logging requests with the facility argument equal to "http" will be logged. One special constant can be used here: "all" means that the logger will log messages regardless of the facility indentifiers associated with them.
Remember that logging facility can be set via the "logFacility" attribute and is by default inherited from the parent server.
See the GenericLogger class for the rest of the common attributes, because all Dwarf loggers are based on it. Other loggers might write log events to physical files, SQL databases, etc., and may provide their own set of attributes. See the SK.gnome.dwarf.log package for the complete list of loggers provided by the Dwarf Server Framework.
Authentication is performed via the login and logout methods declared in the Service interface. Similarly to logging, the authentication requests are in effect propagated to the top-level main server. Therefore there must be a way how to tell the server what to do with these requests. The answer is simple: if a service implementing the Authenticator interface (let's call it the authenticator) is inserted to a server, the server will redirect all authentication requests to this authenticator. The authenticator must therefore implement its methods to perform the real authentication, i.e. checking the user credentials against a database, etc.
In order to make the authentication working, we must add an implementation of the Authenticator interface to the main server. The only available service implementing this interface is the JAASAuthenticator class:
<service classbase="SK.gnome.dwarf." class=".main.MainServer" name="Main Server"> <!-- ... ATTRIBUTES ... --> <!-- ... LOG SERVER ... --> <!-- AUTHENTICATOR --> <service class=".auth.JAASAuthenticator" name="Authenticator"> <set name="logFacility">auth</set> </service> </service>
This service implements its login and logout methods to perform the login module-based authentication, supported by the javax.security.auth.login package. The login configuration required by the login mechanism is specified via the facility argument of the login method. Remember that the authentication facility can be set via the "authFacility" attribute of the service and is by default inherited from the parent server.
Read the Security Guide for more information about the authentication and login module configuration.
A single main server, even with properly configured logging and authentication mechanism, would be pretty useless without a real-use services added to it. Although they may be added directly to the main server via the nested <service ...> configuration elements, the preferred way is to configure the custom service in a separate place and include it to the main configuration file. The advantage of this becomes evident if there are more than one complex services to be added to the main server:
<service classbase="SK.gnome.dwarf." class=".main.MainServer" name="Main Server"> <!-- ... ATTRIBUTES ... --> <!-- ... LOG SERVER ... --> <!-- ... AUTHENTICATOR ... --> <!-- INCLUDED SERVICES --> <include url="file:conf/http.xml"/> <include url="file:conf/smtp.xml"/> <include url="file:conf/ftp.xml"/> </service>
Once configured, the application can be executed by running either the "run.bat" or "run.sh" batch scripts, depending on your OS platform. Each of these scripts accepts an argument with the location of the main configuration file. You can have several different configurations of a single application, or several configurations of many different applications, and switch between them easily by specifying the location of the configuration file on the command line:
C:\Dwarf> run.bat file:conf/main2.xml
There is one more useful feature provided by the framework, although it is not necessary for running the application. It is the server console. Console is a special service which accepts commands from the end user or from another service. Typically, it is used to manage services by entering commands via the interactive command prompt. Since the console's design is modular, other ways of passing the commands to the console may be developed, too. (For example, Dwarf HTTP Server provides a sample application with remote management based on a servlet communicating with the server console.) Console commands are also modular, therefore new commands can be easily created and plugged-in to the console.
The console is an instance of the Console class and must be added to the main server object:
<service classbase="SK.gnome.dwarf." class=".main.MainServer" name="Main Server"> <!-- ... ATTRIBUTES ... --> <!-- ... LOG SERVER ... --> <!-- ... AUTHENTICATOR ... --> <!-- CONSOLE --> <service classbase="SK.gnome.dwarf.main" class=".Console" name="Console"> <set name="prompt">true</set> <service class=".cmd.HelpCmd" name="?"/> <service class=".cmd.HelpCmd" name="help"/> <service class=".cmd.LSCmd" name="ls"/> <service class=".cmd.CSCmd" name="cs"/> <service class=".cmd.ReportCmd" name="report"/> <service class=".cmd.ParamCmd" name="param"/> <service class=".cmd.DumpCmd" name="dump"/> <service class=".cmd.DebugCmd" name="debug"/> <service class=".cmd.TraceCmd" name="trace"/> <service class=".cmd.ThreadsCmd" name="threads"/> <service class=".cmd.PolicyCmd" name="policy"/> <service class=".cmd.PropertiesCmd" name="properties"/> <service class=".cmd.RestartCmd" name="restart"/> <service class=".cmd.ShutdownCmd" name="shutdown"/> </service> </service>
The "prompt" attribute specifies whether the console will be accessible via the interactive command prompt. To get the console prompt you have to press Enter at the system console window and wait for the respond.
The runtime name of each command service is also the name by which the command is visible and may be invoked by the end user. By adding a new command to the console you make it automatically available to the end user with a very little effort.
The detailed command description can be found in the API documentation for the SK.gnome.dwarf.main.cmd package. See also the Console Command Tutorial for the sample developer's guide related to the console commands.
Return to the main page.