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

Factory Services

All of the flexibility we have seen so far in the data access layer is made possible by an underlying service called FactoryService, which is directly accessible to your Java applications. This is exposed through a single method as follows:

Object AppObjects.getObject(string symname, object args);

The idea here is that Aspire will instantiate a class name identified by the symname and call its well-known method, called executeRequest(..), and return whatever that method returns. Aspire uses your config files for this name translation. Here is an example:

Request.MYSYMNAME.classname=MyClass

where MyClass needs to implement the ICreator interface as follows:

public MyClass implements Icreator
{
   Object executeRequest(String reqName, Object args)
   {
      // implement your specific funtionality
   }
}

Aspire, by default, will create your MyClass only once but will call the executeRequest every time a client issues getObject. So in essence, MyClass is a singleton and its semantics are those of a factory that can generate objects. One way to implement a singleton is as follows:

public MyClass implements Icreator, IMySpecialInterface
{
   Object executeRequest(String reqName, Object args)
   {
      // implement your specific funtionality
      return this;
   }
}

Then you can use your class as follows:

IMySpecialInterface  myInterface = 
   (IMySpecialInterface)AppObjects.getObject(IMySpecialInterface.NAME,null);
myInterface.myMethod();

See how you have hidden the implementation completely. You can have some config arguments:

Request.MYSYMNAME.classname=MyClass
Request.MYSYMNAME.arg1=333
Request.MYSYMNAME.arg1=444

And read those arguments as follows in your code:

public MyClass implements Icreator, IMySpecialInterface
{
   Object executeRequest(String reqName, Object args)
   {
      string arg1 = AppObjects.getValue("request." + reqName + ".arg1");         
   }
}

Sometimes you don't want your class to be singleton but rather a true business object that is stateful. Then you can alter your class as following:

public MyClass implements Icreator, IMySpecialInterface, ISingleThreaded
{
   Object executeRequest(String reqName, Object args)
   {
      string arg1 = AppObjects.getValue("request." + reqName + ".arg1");         
   }
}

Aspire will instantiate a new object every time it sees a ISingleThreaded implemented. This programming model is somewhat similar to session beans but is in-process and lightweight. When combined with multirequest executors, you can also achieve limited transactional programming facilities that are quite practical and sufficient for a single database application.

Using XML Config Files

So far you have seen the case where you are using properties files for your configuration. Aspire.jar supports XML config files as well, without ever changing your client code. Consider the following XML config file:

<xml version='1.0' encoding='utf-8' >
<config>
   <keys>
      <key1>val1</key1>
      <key2>val2</key2>
   </keys>
    
   <request name="GetMultiTable">
      <classname>com.ai.db.DBPreTranslateArgsMultiRequestExecutor</classname>
      <Request.1>GetSeries1</Request.1>
      <Request>GetSeries2</Request>
   </request>
       
   <request name="GetTable1">
      <classname>com.ai.data.RowFileReader</classname>
      <filename>aspire:\\samples\\xml-config-files\\sample-data-1.txt</filename>
   </request>
    
   <request name="GetTable2">
      <classname>com.ai.data.RowFileReader</classname>
      <filename>aspire:\\samples\\xml-config-files\\sample-data-1.txt</filename>
   </request>
</config>

Include the XML Config File in aspire.properties

To read both properties files and XML config files, you need the following line pointing to an XML config reader (the following code is actually two lines with no spaces after the = sign):

#request.ApplicationObjects.Config.className=
    com.ai.application.defaultpkg.CConfigWithIncludes
request.ApplicationObjects.Config.className=
    com.ai.extensions.xmlconfig.ConfigWithXMLIncludes

See the commented out section and the new line. And you can include your XML config files in the following line:

application.xmlIncludeFiles=
   aspire:\\samples\\xml-config-files\\xml-sample-file.xml

Accessing Your XML Config Entries

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

public void readYourKeys()
{
   .. usual try and catch stuff if you need
   String key1Value =   AppObjects.getValue("keys.key1");
   String key2Value =   AppObjects.getValue("keys.key2");
}

See the similarity to accessing your properties files. In essence, you can choose to keep your configuration either in XML or properties and your code will still work.

An Equivalent Properties File

Here is an equivalent properties file matching the XML config above.

keys.key1=val1
keys.key2=val2
    
request.GetMultiTable.classname=com.ai.db.DBPreTranslateArgsMultiRequestExecutor
request.GetMultiTable.request.1=GetTable1
request.GetMultiTable.request=GetTable2
request.GetMultiTable.db=<dbalias>

request.GetTable1.classname=com.ai.data.RowFileReader
request.GetTable1.filename=aspire:\\samples\\xml-config-files\\sample-data-1.txt
request.GetTable2.classname=com.ai.data.RowFileReader
request.GetTable2.filename=aspire:\\samples\\xml-config-files\\sample-data-2.txt

Defining Connection Pools

While executing these SQLs, Aspire has to get a connection from the database. Aspire uses two homebuilt connection pool managers for this purpose. You can easily implement your own by implementing the IConnectionPool interface (the following lines with an = sign are actually one line with no spaces):

#********** SimpleConnectionManager definition
#request.AppObjects.connectionManager.className=
   com.ai.db.SimpleConnectionManager

# multiple connection pool manager
# There is no cap on the number of connections 
# Connections will even out based on your demand
request.AppObjects.connectionManager.className=
   com.ai.db.ConnectionPoolConnectionManager1
request.AppObjects.scheduler.className=
   com.ai.scheduler.BasicScheduler
AppObjects.scheduler.timer_interval_in_milli_secs=60000

By default, the connection pool manager is set to the multiple connection pool manager. If you want the simple connection pool manager, comment out these three lines and uncomment the one line corresponding to the SimpleConnectionPoolManager. SimplePoolConnectionManager will close the collection every time it is returned and open a new one when requested. The ConnectionPoolConnectionManager1 will cache the connections and will create a new connection if all of the connections that are in the pool are being used. The timer wakes up every five minutes and closes unused connections and does some other housekeeping.

Additional Features of the Aspire.jar File

In this section, let me briefly discuss the advanced facilities of this small .jar file. In an article in XML Journal two years ago, I presented the idea of retrieving infosets (I am using this term loosely, compared to the W3C InfoSet, but it shares many conceptual similarities) by generating and consuming XML messages from and to relational databases. In short, an infoset is a hierarchical set of nodes where each node is tied to a collection (like a RowSet).

This binding happens declaratively in a config file. Aspire will execute this infoset, execute all the database calls, and create a hierarchical data set called infoset. The infoset can be presented as:

  • Non-typed navigable Java tree (non-typed Java infoset)
  • Typed Java tree (Typed Java infoset)
  • XML (XML infoset).

The resulting infoset then can be transformed using either Java or XSLT. More recently, this idea was published at O'Reilly as "Transparent Data Pipelines for JSP." You can use flat files, SQL, stored procedures, and Java components to declaratively construct these infosets.

In addition, you can:

  • Have Aspire manage your Tomcat sessions using pluggable session managers, with a default supplied.
  • Have Aspire authenticate users with a couple of default authenticators.
  • Have Aspire expose your business components (both procedural and declarative) as SOAP services.
  • Import and export data into and out of the database.
  • Use a simplified Aspire transformation in conjuction with tools like Dreamweaver and FrontPage to supplement JSP programming.
  • Paint JavaScript-based trees on your screen where each node on your tree is tied to a symbolic name pointing to a stored procedure, SQL statement, or Java code. You can save viewstate of your page using JavaScript.

If you would like to make use of this advanced functionality, email me at so that I can point to you additional documentation.

Help

For any questions regarding the usage of this .jar file, email me at .

Additional References

Satya Komatineni is the CTO at Indent, Inc. and the author of Aspire, an open source web development RAD tool for J2EE/XML.


Return to ONJava.com.