Advanced
In this chapter, we will see how to use advanced features of the TROIKA.ASP framework. This will be of great help in writing your web applications, making your coding faster and more efficient.
Persistence code generator
Persistence code generator is a powerful tool which can be used to generate Data Access Objects (DAO) and Value Object (VO) classes for your web application.
The advantages are as follows:
- Fewer errors, the code generated based on declaration XML eliminating the possible typos and other bugs due to misspelling. The XML declaration file maps fields to table columns.
- Fast to get basic functionality working – insert, update, delete, find, following few basic naming conventions.
- Leave seamless upgrade and bug fix path for the code generated classes. For example, you have found a better way to implement certain DAO method; you can amend the appropriate template and rerun the code generator. And all your DAO/VO classes are improved and you do not have to go through each of them to fix the problem manually.
System requirements
- Microsoft Access 2005 or later
- Microsoft ADO 2.8 or later
- Ant 1.6 or later, download it if you have not got it from
http://ant.apache.org/ - Java SDK 1.4 or later,
http://java.sun.com/j2se/1.4.2/download.html - Microsoft Windows Script Host Version 5.6
Let me show you how it works on a simple example.
Simple DAO/VO objects generator tutorial
- Create database table. To convenience, I have created an empty Microsoft Access 2003 database and put it here. WEB-INF/data/helloworld.mdb
- Create member table:
CREATE TABLE member ( [MemberId] COUNTER CONSTRAINT ID PRIMARY KEY, [FirstName] TEXT(25), [LastName] TEXT(30), [Age] NUMBER ) -
Map member table columns to the Member DAO/VO classes fields, see troika-asp/build/generator/dao-definitions.xml
<!--<!DOCTYPE dao SYSTEM "dao-definitions.dtd">--> <dao> <entity name="Member" table="member"> <field name="memberId" type="Identity" size="1" /> <field name="firstName" size="25" /> <field name="lastName" column="Surname" size="30" /> <field name="age" type="Integer" size="1" /> <finder fields="memberId" /> <finder fields="firstName" /> <finder fields="firstName lastName" /> <finder fields="age" methodName="searchMembersByAge" sort="age" order="asc" /> <insert /> <update /> <delete /> </entity> </dao>Tip, uncomment dao-definitions.dtd if you would like to validate the document. Do not forget to comment it out again when running code generator or you will get an error.
- Setup JAVA_HOME and ANT_HOME environment variable as appropriate
- Open a new window command line window. Change to directory troika-asp/build
-
Run the following command:
>build generate- This will execute ANT build script troika-asp/build/build.xml with “generate” target.
- The ANT script will generate another temporary ANT script troika-asp /build/generator/generator_out/generator.xml
- This in turn will generate two files: MemberDAO.js and MemberVO.js in generator/generator_out directory and copies it to troika-asp/WEB-INF/classes/models
-
MemberVO is a Value Object it defines all available fields according to your declarations in dao-definitions.xml file.
This is a constructor of MemberVO class
function MemberVO() { this.memberId = null; this.firstName = null; this.lastName = null; this.age = null; } -
MemberDAO is implementation of Data Access Object pattern. It encapsulates common data manipulation methods as per dao-definitions.xml file.
The following two lines of code tell JavaScript that new class MemberDAO extends Ado class inheriting all its methods.
MemberDAO.prototype = new Ado(); MemberDAO.prototype.constructor = MemberDAO;This is a constructor for MemberDAO class.Parameter connectionString is a database specific connection string
function MemberDAO(connectionString) { if (arguments.length) { this.init(connectionString); } }We override super class (Ado) implementation of init method here. You can put other initialisation code here. Warning, make a copy of the DAO class first or it could be overridden next time you run the code generator.
MemberDAO.prototype.init = function (connectionString) { Ado.prototype.init.call(this, connectionString); return this; };There are the following methods:
-
void insert (memberVO) -
This creates a new row in a table using all fields from MemberVO objects except the identity field Id. The member table will auto generate the value for Id column.
If a value of a field is longer then defined in dao-definitions.xml file size attribute it will be truncated to the size.
- Parameters:
- memberVO – An instance of MemberVO class. Note that all fields need to be set to some value or to an empty string; otherwise you will get “field undefined” error.
- Usage:
-
var vo = new MemberVO(); vo.firstName = ”John”; vo.lastName = ”Smith”; vo.age = 33; var dao = new MemberDAO(connStr); dao.insert(vo);
-
void update (memberVO) -
This updates a row in a database identified by memberId value.
If a value of a field is longer then defined in dao-definitions.xml file size attribute it will be truncated to the size.
- Parameters:
- memberVO – An instance of MemberVO class. Note that all fields need to be set to some value or to an empty string; otherwise you will get “field undefined” error.
- Usage:
-
var vo = new MemberVO(); vo.memberId = 11; vo.firstName = ”John”; vo.lastName = ”Smith”; vo.age = 35; var dao = new MemberDAO(connStr); dao.update(vo);
-
void delete (id) -
Deletes a row in a database if found by id.
- Parameters:
- id – A unique Id of the row in a database.
- Usage:
-
new MemberDAO(connStr) .delete(11);
The code generator has also created a number of finder methods. By default the generator uses fields attribute of finder tag to generate finder method name in following format:
Object findByField1[AndField2]..(memberVO, recordCount)For example,
<finder fields="firstName lastName"/>Results in:
-
Object findByFirstNameAndLastName(memberVO, recordCount)You can override, the default signature name using optional methodName attribute of the finder tag.
Object findByMemberID (memberVO, recordCount)Object findByFirstName (memberVO, recordCount)Object findByFirstNameAndLastName (memberVO, recordCount)Object searchMembersByAge (memberVO, recordCount) -
Finds one, many of none objects searching using field values from memberVO as the method signature suggests.
- Parameters:
-
memberVO – An instance of MemberVO class. Some of the field values of this instance can be used in search query. For example, the findByFirstNameAndLastName finder takes firstName and lastName fields in the search.
recordCount – optional parameter.
- If it is omitted then the finder will return only one instance of MemberVO or undefined value if nothing found
- If it defined, it could be a positive integer value or special string “all”, which means return all values as a list of VO objects.
All finder methods support polymorphic argument list. You can either supply memberVO into the finder methods or the actual search values as parameter list.
For example the following two calls are equivalent:
findByFirstNameAndLastName ( memberVO, recordCount) findByFirstNameAndLastName ( firstName, lastName, recordCount) - Returns:
-
Object – JavaScript object or undefined. The return value will be a subject of the following conditions:
- If there is no result each finder returns undefined value.
- If there is only one row in search results, a new instance of memberVO returned.
- If there are multiple results, a list of memberVO instances will be returned.
- Usage:
-
var dao = new MemberDAO(connectionStr); //search member table for a row with Id - 4 var memberVO = dao.findByMemberId(4); //check to see if we have found an object if (memberVO) { out("First Name is " + memberVO.firstName); } //*** next example *** var vo = new MemberVO(); vo.firstName = "John"; vo.lastName = "Smith"; //search by first/last name and return first 5 object in a list var result = dao.findByFirstNameAndLastName(vo, 5); /* This equivalent to a call like this: var result = dao.findByFirstNameAndLastName( "John", "Smith", 5); */ if (result) { for (var i = 0; i < result.size(); i++) { out("Age is " + result.get(i).age); } } //*** next example *** //search members with age of 33, return all results result = dao.searchMembersByAge(33, "all"); if (result) { for (var i = 0; i < result.size(); i++) { out("Last Name is " + result.get(i).lastName); } }
-
-
Please run:
..\troika-asp\build>cscript //nologo tests.wsf //job:dao Driver={Microsoft Access Driver (*.mdb)};Dbq=.. \troika-asp\build/../WEB-INF/data/helloworld.mdb; Testing findByMemberId() test: First Name is John Testing findByFirstNameAndLastName() test: Age is 33 Testing searchMembersByAge() test: Last Name is Pan Testing searchMembersByAge() test: Last Name is Smith - Study/Modify the source code of tests.wsf file.
- If you do not have Microsoft scripting installed please download it from here
http://msdn2.microsoft.com/en-us/library/ms950396.aspx - That is the end of the Code Generator tutorial. Congratulations!