ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

For Tomcat Developers, Aspire Comes in a JAR
Pages: 1, 2, 3, 4, 5

Sample Code for Reading Configuration



Before diving into the data access code of Aspire, let us spend a couple of minutes with the configuration API. Let's use Aspire to read a couple of config file entries. Create a config file called myconfig.properties with the following text:

Module1.key1=20
Module2.key2=14

Include this myconfig.properties file in the master aspire.properties file as follows (the second and third lines here are actually one line with no spaces).

Directories.aspire=c:\\your-webapp-root
application.includeFiles=aspire:\\properties\\myconfig.properties,
     aspire:\\another-config-file

The symbolic name aspire is a directory alias pointing to your webapp root, but it can point to any directory on your system. Restart Tomcat so that this file gets picked up. Here is the sample Java code to demonstrate the reading configuration.

import com.ai.application.interfaces.*;
import com.ai.application.utils.*;

public void somefunction()
{
   try 
   {
      String default = "67";
      String val1 = AppObjects.getValue("Module1.key1",default);
      String val2 = AppObjects.getValue("Module2.key2");
   }
   catch(com.ai.application.interfaces.ConfigException x)
   {
      AppObjects.log("Error: Mandatoty configuration entry missing",x);
   }
}

AppObjects is a static wrapper utility class. The function getValue() will take a hierarchical key and returns its value. If the value is not found, a ConfigException will be thrown. If you use a getValue() that takes a default, then instead of throwing an exception, the default value will be returned. You can use the exception version of the call to read in mandatory config entries.

In addition to handling config exceptions, the code above also demonstrates how to use the log facility available in Aspire. Almost all of Aspire's exceptions are nested exceptions. And Aspire's logging facility will automatically log them to the log file, including the nested exceptions. You can prevent seeing these exceptions in the log file using the Select and Exclude filters. Aspire uses a configuration entry for controlling logging adapters. For example, you can change the logging adapter to one of your choice, as long as you write an implementation for it.

Here is the log implementation object entry in the properties file:

request.ApplicationObjects.Log.className=com.ai.application.defaultpkg.Clog

where Clog is an implementation of com.ai.application.interfaces.ILog. You can take a look at the source code for both classes to implement your own.

Reading Relational Data From Files

Although configuration and logging are essential aspects of an application, you may or may not consider them compelling enough to adapt them for your application. With that in mind, let me present Aspire's data abstraction layer, which I believe is complete (comprehensive), easy, practical, fluid, and stays out of your way. Let us start by reading a flat file called data.txt with the following entries:

col-one|col-two|col-three
10|44|44
33|44|33

Furthermore, assume that the rows are subdivided into columns using the pipe (|) character, giving the appearance of a database call.

Here is sample code to read the collection of rows and columns from the above data file:

import com.ai.application.interfaces.*;
import com.ai.application.utils.*;
import com.ai.data.*;
    
public void someFunction()
{
   IDataCollection col;
   try
   {
      Hashtable args = null;
      col = (IDataCollection)AppObjects.getObject("MYDATA",args);
      IIterator rowItr = col.getIIterator();
      for(rowItr.moveToFirst();!rowItr.IsAtTheEnd();rowItr.moveToNext())
      {  
         IDataRow dr = rowItr.getCurrentElement();
         String value = dr.getValue("col-one");
      }
   }
   catch(com.ai.application.interfaces.RequestExecutionException x)
   {
      AppObjects.log("Error: Could not get data collection. Factory error",x);
   }
   catch(com.ai.data.DataException x)
   {
      AppObjects.log("Error: Data related error",x);
   }
   finally
   {
      col.closeCollection();
   }
}

Aspire's idea of abstract data and all the relevent interfaces are defined in the package com.ai.data. IDataCollection is the central interface representing the idea of a collection of rows, where each row can be any object. One such object is represented by IDataRow. You would use an IIterator to walk through this set of rows. If there were any errors in the data abstraction layer, you would receive an exception of type com.ai.data.DataException.

The mysterious looking call AppObjects.getObject("MYDATA",args) requires explanation. MYDATA is a symbolic request name that Aspire will resolve to a file reader (in this case). The output of that file reader will be returned to the caller as an IDataCollection. args is a map (hashtable) of arguments that could be used by the file-reader. Aspire uses the Configuration abstraction to translate the symbolic name MYDATA to a Java class. Following is the property file section that is required for this translation.

Request.MYDATA.classname=com.ai.data.RowFileReader
Request.MYDATA.filename=aspire:\\datafiles\\mydata.txt

Aspire maps the MYDATA symbolic request name to a Java class called com.ai.data.RowFileReader and invokes its well-known method with the hashtable of arguments passed in. It is the responsibility of RowFileReader to return an IDataCollection, which gets cast to that type by the client. com.ai.data.RowFileReader is one of Aspire's prebuilt parts. Aspire has a few of these pre-built parts that you can make use of. See also how the directory alias is again used here in specifying the filename.

The point to note is that the true implementation of data access (file opens, reads, closes) is hidden (or abstracted out) and externalized (through config files), easing maintenance. Let us look now into the "fluidity" aspect of the abstraction by looking at how we can read a similar set of rows and columns using SQL.

Pages: 1, 2, 3, 4, 5

Next Pagearrow