Building a Custom Web Server

You may want to add additional features to the web server with your own servlets. This document discusses how to do this.

The build process relies on the Ant build tool from The Jakarta Project. A build.xml file is included, and the only file you need to modify for your own configuration is the build.properties file.

An additional tool, called TiniAnt, is also required. This supplies an Ant task that knows how to work with and convert TINI executables. It can be found at http://tiniant.sourceforge.net/index.html. Version 1.2.0 or later is required.

Subject Menu


Including Your Own Source

The build process allows you to include your own source. You will need to modify at least two build properties: src.paths, src.files, and possibly dependency.classpath.

Place the location of the source files in src.paths, and a list of files in src.files. If your code depends on further libraries, you may need to modify dependency.classpath as well. See the build configuration section for more details.

Additionally, if any of your classes are accessed via a Class.forName call, or for that matter, any reflection call, then you must also add those full classnames to reflect.classes. The reason for this is that reflection information for all classes not specified here is excluded from the build.

[Top]


Including Your Own Classes

It is also possible to include your own pre-built classes in the build process. To do this, define a dependency group in a file specified in dependency.files, include the group name in dependency.groups, and add the location of the classes to dependency.classpath.

Furthermore, the same note about reflection applies here as it does to your own source files. You need to add any "reflected" classnames to reflect.classes. This includes any class obtained from a call to Class.forName.

A more elaborate explanation

Including pre-built libraries and classes in your server binary deserves more explanation, as it is probably the most confusing aspect of the build process. The following steps will guide you through an example that illustrates the proper way to go about this. Unfortunately, it is a bit of a manual process due to the way the TINI BuildDependency program works.

  1. Create a dependency file such as my_dep.txt.
  2. Determine which classes are used. For example, your servlets may depend on:
    • com.db.DBConnectionPool and
    • com.db.DBUtils
    In turn, com.db.DBConnectionPool may depend on:
    • com.db.DBConnectionFactory and
    • com.db.util.ObjectPool
  3. Pick a descriptive name for this "group" of classes. (A dependency group simply means "a group of classes on which your code depends"). This name will refer to all of the above "dependencies". For example, choose DB_TOOLS. Then, place this line into my_dep.txt (note that the line may be wrapped, but should be on one line):
    DB_TOOLS=com.db.DBConnectionPool;
             com.db.DBUtils;
             com.db.DBConnectionFactory;
             com.db.util.ObjectPool
  4. Add the group we've just created to dependency.groups. For example, say your code also depends on OneWireContainer10. The proper setting, then, will look something like this:
    dependency.groups=OneWireContainer10,DB_TOOLS
    Additionally, if any of the classes added here need to be accessed with reflection, then be sure to add the full classname to reflect.classes.
  5. Add this new dependency file to the dependency.files property:
    dependency.files=<path_to>/my_dep.txt
  6. Lastly, tell the build tools where to find these com.db.* and com.db.util.* classes by adding the appropriate path to dependency.classpath. For example, a JAR file called dbtools.jar may contain these classes:
    dependency.classpath=<path_to>/dbtools.jar
    If the classes reside do not reside in a JAR, but in a directory called dbtools, then the setting may instead look like:
    dependency.classpath=<path_to>/dbtools

It is possible to set up a more complex set of dependencies, with multiple groups and files. However, you are referred to the BuildDependency documentation in your TINI firmware distribution for more information.

[Top]


Build Configuration — The build.properties File

The build.properties file is the only place you are required to manage your build configuration. The syntax requrements are only that a forward slash (/) for the file separator, and a colon (:) for the path separator, are used. Also, any non-required properties may be left unspecified.

Note: If you choose to use backslashes (\) for your paths, say, in Windows, then you must use pairs (eg. tini.path=C:\\Java\\tini1.17). This is because in properties files, backslashes are treated specially. They act to change the meaning of the following character. Please consult the Java documentation for more information.

tini.path

This points to the location of your TINI firmware installation. For example:

tini.path=C:/Java/tini1.17

This property is required.

src.paths

This points to the location(s) of your source files. For example:

src.paths=mysrc:myservlets/src

A path separator is used between different paths.

src.files

A comma- or space-separated list of source files. This may be specified using Ant-style wildcard patterns. For example:

src.files=com/mycompany/util/*.java,com/theircompany/**/*.java

It is not a good idea to specify **/*.java since that may include unwanted source files. Instead, be more specific with the package structure, as in the above example.

include.loaderServlet

When this property is set to true, a special servlet that can load arbitrary servlets is included in the binary. The property is ignored if the build is not for version 1.10 or later firmware. Starting with version 1.10, the TINI firmware added classloading capabilities, and this makes it possible to include reloading functionality.

The full classname of the servlet is com.qindesign.servlet.LoaderServlet, and an example of using it in the servlet.props file is as follows:

Loader.mapping=/servlet/Loader/*
Loader.class=com.qindesign.servlet.LoaderServlet
Loader.initParams=classpath=/web/servlet/classes

The "/*" is necessary at the end of the mapping. More details about this special servlet can be found in the Servlet Reloading document.

The binary will be larger with this feature enabled because much more reflection information has to be included. Note that the build process automatically includes this class in the reflect.classes build property for you.

include.servletReloading

When this property is set to true, support for servlet reloading is added to the binary. It is ignored if the build is not for version 1.10 or later firmware. Starting with version 1.10, the TINI firmware added classloading capabilities, and this makes it possible to include reloading functionality.

The binary will be larger with this feature enabled because much more reflection information has to be included.

Please see the Servlet Reloading document for more details.

include.templateEngine

When this property is set to true, the template engine is included in the build. If any servlets use this, or if the TemplateDemo example servlet is included, then this property must be set.

Please see the Template Guide for additional information.

include.authentication

When this property is set to true, support for HTTP authentication is included in the build. If any servlets use this, or if the AuthExample example servlet is included, then this property must be set.

dependency.files

A comma-separated list of dependency files for the TINI development kit's build-dependency program. Note that the owapi_dep.txt file containing all the 1-Wire dependencies is automatically included, and does not need to be specified here. For example:

dependency.files=my_dep_file.txt

When writing a dependency file, do make sure that any defined group names don't conflict with those in another dependency file. The build-dependency program internally creates one big list and seems to ignore conflicts. For example, don't have two groups named "ROOT" when substituting for a base package name. Instead, use a more meaningful name such as "COM_COMPANY_ROOT".

dependency.groups

A comma-, colon-, or semicolon-separated list of dependency group names. You may include groups from the TINI development kit's owapi_dep.txt file, or from your own dependency files listed in the dependency.files property. For example:

dependency.groups=Switches,\
                  OneWireContainer10,\
                  OneWireContainer21,\
                  OneWireContainer20,\
                  OneWireContainer23,\
                  OneWireContainer09,\
                  OneWireContainer01,\
                  ExampleServlets

Additionally, if any of the classes added here need to be accessed with reflection, then be sure to add the full classnames to reflect.classes. For example, the firmware protocol handler classes, such as com.dalsemi.protocol.http.Handler from the "HTTP" group, are accessed through reflection, as are all the other com.dalsemi.protocol.protocol_name.Handler classes, and also all the 1-Wire container classes.

dependency.classpath

This specifies a CLASSPATH-like list of paths and archives containing classes specified by the dependency group names. Any TINI-related library, such as owapi.jar and the 1.1 modules.jar, is automatically included, and does not need to be specified here. For example:

dependency.classpath=mylibrary.jar

reflect.classes

The TINI 1.10 or later firmware requires that reflection information be included in the build process if Class.forName is to work. Because both the servlet container and 1-Wire adapters use this call to create servlets and 1-Wire containers, any related classes must be included in this list. For example:

reflect.classes=com.qindesign.servlet.DefaultServlet,\
                com.qindesign.servlet.example.RequestInfoServlet,\
                com.qindesign.servlet.example.AuthExampleServlet,\
                com.qindesign.servlet.example.TiniInfoServlet,\
                com.qindesign.servlet.example.OneWireServlet,\
                com.qindesign.servlet.example.SwitchInclude,\
                com.qindesign.servlet.example.TemperatureInclude,\
                com.dalsemi.onewire.container.OneWireContainer05,\
                com.dalsemi.onewire.container.OneWireContainer12,\
                com.dalsemi.onewire.container.OneWireContainer1F,\
                com.dalsemi.onewire.container.OneWireContainer10,\
                com.dalsemi.onewire.container.OneWireContainer21,\
                com.dalsemi.onewire.container.OneWireContainer20,\
                com.dalsemi.onewire.container.OneWireContainer23,\
                com.dalsemi.onewire.container.OneWireContainer09,\
                com.dalsemi.onewire.container.OneWireContainer01

Note that all servlets must be included here, as well as any of the firmware protocol handler classes, 1-Wire containers, and all classes accessed by a dynamically loaded servlet.

[Top]


Other Build-Related Files

This section discusses the other files needed in the build process.

The build.xml file

The build.xml file is the Ant build script. Its default task will automatically create a TINI executable named webserver.tini in the tini/bin/ directory.

By default, all compiled classes will be written to a directory named classes/. This can be changed by changing the javac.destination property to something else.

[Top]