I spent the day today figuring out how to use Torque a stand alone
(non-turbine) application. It was not hard once I figured out
where all the config files were and how to initialize torque without
using turbine. I was documenting it for myself so I wouldn't forget
and decided to expand my notes a little bit and put it out to the
mailing list in the hopes that other new users might find it helpful.
Let me preface by saying I am not real experienced in using databases
or torque so I am sure there are better ways to do things or things
I might have left out. But I tried to be detailed in all my steps and
this test worked for me. If anyone wants to use this as a starting
point and expand on it or xdoc it, feel free. I did this under Redhat
Linux 7.1 using the bash shell. Windows users adjust the commands
accordingly.
Almost everything in here assumes that you have the ant and cvs
commands in your PATH enviroment variable.
Step 1) Build torque
---------------------
Download torque source. I do all my downloads under a directory called
projects.
> cd ~/projects
> cvs -d :pserver:[EMAIL PROTECTED]:/home/cvspublic login
> CVS password: anoncvs
> cvs -d :pserver:[EMAIL PROTECTED]:/home/cvspublic checkout
jakarta-turbine-torque
Under the jakarta-turbine-torque directory there is a README.txt that
says
you must rename the build.properties.sample file to build.properties.
There
is no build.properties.sample file but there is a default.properties
file.
I made the assumption that this is the file intended and copied
default.properties
to build.properties.
Inside build.properties you need to define
velocity.jar
xerces.jar
village.jar
log4j.jar
jdbc.jar
junit.jar
commons-collections.jar
commons-util.jar
to point to the appropriate jar files. I am still not sure why the jars
are
not available under the lib directory of the jakarta-turbine-torque cvs
tree.
You could take the time to download all the source for these jars and
build
them. I started down this road but that required me to find all the jars
or
source for the jars that these jars are dependent on... and so on.
Instead
I looked around and was able to get all but the last 2 jars from the
jakarta-turbine-2 cvs repository. Use the following cvs command to just
checkout the lib directory from jakarta-turbine-2 project.
> cvs -d :pserver:[EMAIL PROTECTED]:/home/cvspublic checkout
jakarta-turbine-2/lib/
For the commons jars I had to get the project source from cvs and build
the jars
> cd ~/projects
> cvs -d :pserver:[EMAIL PROTECTED]:/home/cvspublic checkout
jakarta-commons
> cd jakarta-commons/collections
> ant dist
NOTE: must have a xerces jar in your classpath for compile to work.
These
steps generate the commons-collections.jar under the
jakarta-commons/collections/dist directory.
This also assumes that you are still logged into the cvs server. If not,
then
relogin.
> cd ~/projects
> cvs -d :pserver:[EMAIL PROTECTED]:/home/cvspublic checkout
jakarta-commons-sandbox
> cd jakarta-commons-sandbox/util
> ant
NOTE: must have a xerces jar in your classpath for compile to work.
These steps
generate the commons-util-0.1-dev.jar under the
jakarta-commons-sandbox/util
directory.
I copied all the jars to a common lib directory and defined lib.repo to
be this
directory inside the ~projects/jakarta-turbine-torque/build.properties
file.
My final ~projects/jakarta-turbine-torque/build.properties file was as
follows:
#####################################################################
#---------------- Start File ----------------------------------------
#####################################################################
# -------------------------------------------------------------------
# B U I L D P R O P E R T I E S
# -------------------------------------------------------------------
# These properties are used by the Torque build, you may override
# any of these default values by placing property values in
# your ${user.home}/build.properties file.
# -------------------------------------------------------------------
name = Torque
project = torque
version = 1.0
package = org.apache.${project}
final.name = ${project}-${version}
build.dir = ./bin
build.src = ${build.dir}/src
build.dest = ${build.dir}/classes
build.test = ${build.dir}/test
src.dir = ./src
test.dir = ${src.dir}/test
docs.src = ./xdocs
docs.dest = ./docs
javadoc.destdir = ./docs/api
jakarta.site2 = ../jakarta-site2
year = 1999-2001
debug = on
optimize = off
deprecation = off
# You must set these values here, or in your
# ${user.home}/build.properties file in order
# to build Torque:
lib.repo = /usr/local/java/lib
velocity.jar = ${lib.repo}/velocity-1.2-dev.jar
xerces.jar = ${lib.repo}/xerces-1.3.0.jar
village.jar = ${lib.repo}/village-1.5.3-dev.jar
log4j.jar = ${lib.repo}/log4j-1.1.jar
commons-collections.jar = ${lib.repo}/commons-collections.jar
commons-util.jar = ${lib.repo}/commons-util-0.1-dev.jar
jdbc.jar = ${lib.repo}/jdbc2_0-stdext.jar
junit.jar = ${lib.repo}/junit-3.2.jar
#####################################################################
#---------------- End File ----------------------------------------
#####################################################################
Now that we have all the needed jars that torque depends on,
go into jakarta-turbine-torque directory and build torque
> cd ~/projects/jakarta-turbine-torque
> ant dist
This creates ~/projects/jakarta-turbine-torque/bin directory
which contains all the parts need to use torque. It also includes
torque-1.0.zip which has everything you need nicely bundled up
to allow your to relocate it where ever you want.
Step 2) Deploy torque
----------------------
Unpack torque-1.0.zip where you want to develop your app. For me
once again it was under my projects directory
> cd ~/projects
> unzip ./jakarta-turbine-torque/bin/torque-1.0.zip
This will build a ~/projects/torque directory. Inside this directory
is the build.properties and build.xml files. For some reason the
permissions were all screwed up in this unpacked torque directory.
I had to fix these permissions to allow me read/write/execute access
to the subdirectories.
Step 3) Create your project configuration files.
----------------------------------------------------------------------
Edit ~/projects/torque/build.properties. I changed the project name
to be "my-test". My database was mysql which is the default so I
did not change that. I changed the targetPackage to be my java package
name "com.digitalevergreen.mytest.om". I set databaseUser and
databasePassword
to be my mysql admin user id and password. I changed the databaseUrl
to create a table called MY_TEST_DB. Instead of listing out the whole
file, I will only list the lines I changed in build.properties.
project=my-test
targetPackage=com.digitalevergreen.mytest.om
databaseUrl = jdbc:mysql://127.0.0.1/MY_TEST_DB
databaseUser = adminuser
databasePassword = adminpassword
Because I changed my project name to my-test I have to create a
file called my-test-schema.xml under the ~/projects/torque/schema
directory. This will contain the xml definition of our objects
and database.
For my example test case I chose a book catalog. My schema contains
three tables. I have a table that contains author information (first,
middle and last name), a table that contains publisher information
(name),
and the last table contains book information (Title, copyright info, and
ISBN). The author id, and publisher id will be foreign keys in the
book table. My schema xml is shown below
<?xml version="1.0" encoding="ISO-8859-1" standalone="no" ?>
<!DOCTYPE app-data SYSTEM
"http://jakarta.apache.org/turbine/dtd/database.dtd">
<!-- =============================================================== -->
<!-- ==================== START SCHEMA ============================ -->
<!-- =============================================================== -->
<app-data>
<database>
<table name="BOOK">
<column name="BOOK_ID" required="true" autoIncrement="true"
primaryKey="true" type="INTEGER" javaName="Id"/>
<column name="TITLE" required="true" type="VARCHAR" size="255"/>
<column name="COPYRIGHT" type="VARCHAR" size="255"/>
<column name="ISBN" type="VARCHAR" size="24" javaName="ISBN"/>
<column name="PUBLISHER_ID" type="INTEGER"/>
<column name="AUTHOR_ID" type="INTEGER"/>
<foreign-key foreignTable="PUBLISHER">
<reference local="PUBLISHER_ID" foreign="PUBLISHER_ID"/>
</foreign-key>
<foreign-key foreignTable="AUTHOR">
<reference local="AUTHOR_ID" foreign="AUTHOR_ID"/>
</foreign-key>
</table>
<table name="PUBLISHER">
<column name="PUBLISHER_ID" required="true" primaryKey="true"
type="INTEGER" autoIncrement="true" javaName="Id"/>
<column name="NAME" type="VARCHAR" size="128" />
</table>
<table name="AUTHOR">
<column name="AUTHOR_ID" required="true" primaryKey="true"
type="INTEGER" autoIncrement="true" javaName="Id"/>
<column name="FIRST_NAME" type="VARCHAR" size="128" />
<column name="MIDDLE_NAME" type="VARCHAR" size="128" />
<column name="LAST_NAME" type="VARCHAR" size="128" />
</table>
</database>
</app-data>
<!-- =============================================================== -->
<!-- ==================== END SCHEMA ============================== -->
<!-- =============================================================== -->
Step 4) Run Torque to build your source files
------------------------------------------------------
Run torque to build the object model and map source files.
> cd ~/projects/torque
> ant
Hopefully you will then see output similar to
> Searching for build.xml ...
> Buildfile: /home/sdavis/projects/torque/build.xml
>
> main:
>
> init-tasks:
>
> project-sql:
> +------------------------------------------+
> | |
> | Generating SQL for YOUR Turbine project! |
> | Woo hoo! |
> | |
> +------------------------------------------+
> /home/sdavis/projects/torque/src/sql/report.my-test.sql.generation
> Resolver: used database.dtd
>
> init-tasks:
>
> project-om:
> +------------------------------------------+
> | |
> | Generating Peer-based Object Model for |
> | YOUR Turbine project! Woo hoo! |
> | |
> +------------------------------------------+
> /home/sdavis/projects/torque/src/java/report.my-test.om.generation
> Resolver: used database.dtd
> Resolver: used database.dtd
>
> BUILD SUCCESSFUL
>
> Total time: 9 seconds
If you did see this then you should have java source files under
~projects/torque/src/java/com/digitalevergreen/mytest/om/
directory that are similar to the following:
-rw-r--r-- 1 sdavis users 509 Sep 24 23:27 Author.java
-rw-r--r-- 1 sdavis users 629 Sep 24 23:27 AuthorPeer.java
-rw-r--r-- 1 sdavis users 15331 Sep 24 23:27 BaseAuthor.java
-rw-r--r-- 1 sdavis users 14828 Sep 24 23:27
BaseAuthorPeer.java
-rw-r--r-- 1 sdavis users 15731 Sep 24 23:27 BaseBook.java
-rw-r--r-- 1 sdavis users 19104 Sep 24 23:27
BaseBookPeer.java
-rw-r--r-- 1 sdavis users 13240 Sep 24 23:27
BasePublisher.java
-rw-r--r-- 1 sdavis users 13994 Sep 24 23:27
BasePublisherPeer.java
-rw-r--r-- 1 sdavis users 505 Sep 24 23:27 Book.java
-rw-r--r-- 1 sdavis users 625 Sep 24 23:27 BookPeer.java
drwxr-xr-x 2 sdavis users 4096 Sep 24 23:27 map
-rw-r--r-- 1 sdavis users 515 Sep 24 23:27 Publisher.java
-rw-r--r-- 1 sdavis users 635 Sep 24 23:27
PublisherPeer.java
Step 5) Create the database and tables
--------------------------------------------------------------
I thought there was a way to have torque automatically create the
database but I could not figure out how to make it do that. I manually
created the database and then used the torque generated sql statements
to set up the tables.
> cd ~/projects/torque/src/sql
> mysql -u <user id> -p<password> mysql
mysql> create database MY_TEST_DB;
mysql> quit
> mysql -u <user_id> -p<password> MY_TEST_DB < my-test-schema.sql
Step 6) Make it all usable in a stand alone program
--------------------------------------------------------------
Ok, all that was great. We have a bunch of java source files and a
database to go with them. How do we use it? It actually turned out
to be pretty easy once I tracked down the initialization requirements
in the Torque code. Torque only requires you to initialize the
database info... but you will get system out errors from log4j if you
don't initialize it also. I created the following properties file in
~/projects/torque/mytest.properties.
# -------------------------------------------------------------------
# Begin mytest.properties
# -------------------------------------------------------------------
# -------------------------------------------------------------------
#
# D A T A B A S E S E R V I C E
#
# -------------------------------------------------------------------
# These are your database settings. Look in the
# org.apache.turbine.util.db.pool.* packages for more information.
# The default driver for Turbine is for MySQL.
#
# The parameters to connect to the default database. You MUST
# configure these properly.
# -------------------------------------------------------------------
services.DatabaseService.database.default=default
services.DatabaseService.database.default.driver=org.gjt.mm.mysql.Driver
services.DatabaseService.database.default.url=jdbc:mysql://localhost:330
6/MY_TEST_DB
services.DatabaseService.database.default.username=adminuser
services.DatabaseService.database.default.password=adminpassword
# The number of database connections to cache per ConnectionPool
# instance (specified per database).
services.DatabaseService.database.default.maxConnections=3
# The amount of time (in milliseconds) that database connections will be
# cached (specified per database).
#
# Default: one hour = 60 * 60 * 1000
services.DatabaseService.database.default.expiryTime=3600000
# The amount of time (in milliseconds) a connection request will have to
wait
# before a time out occurs and an error is thrown.
#
# Default: ten seconds = 10 * 1000
services.DatabaseService.database.connectionWaitTimeout=10000
# The interval (in milliseconds) between which the PoolBrokerService
logs
# the status of it's ConnectionPools.
#
# Default: No logging = 0 = 0 * 1000
services.DatabaseService.database.logInterval=0
# These are the supported JDBC drivers and their associated Turbine
# adapter. These properties are used by the DBFactory. You can add
# all the drivers you want here.
services.DatabaseService.database.adapter=DBMM
services.DatabaseService.database.adapter.DBMM=org.gjt.mm.mysql.Driver
# Determines if the quantity column of the IDBroker's id_table should
# be increased automatically if requests for ids reaches a high
# volume.
services.DatabaseService.database.idbroker.cleverquantity=true
# Determines if IDBroker should prefetch IDs or not. If set to false
# this property has the effect of shutting off the housekeeping thread
# that attempts to prefetch the id's. It also sets the # of id's
grabbed
# per request to 1 regardless of the settings in the database.
# Default: true
services.DatabaseService.database.idbroker.prefetch=true
services.DatabaseService.earlyInit = true
# -------------------------------------------------------------------
#
# log4j
#
# -------------------------------------------------------------------
# Need to have log4j "appenders" for Torque or log4j will generate
# system out errors.
log4j.category.org.apache.torque = INFO, torque
log4j.appender.torque = org.apache.log4j.FileAppender
log4j.appender.torque.file = ./mytest.log
log4j.appender.torque.layout = org.apache.log4j.PatternLayout
log4j.appender.torque.layout.conversionPattern = %d [%t] %-5p %c - %m%n
log4j.appender.torque.append = false
# -------------------------------------------------------------------
# End mytest.properties
# -------------------------------------------------------------------
I then created the file
~/projects/torque/src/java/com/digitalevergreen/mytest/MyTest.java
which contains code to initialize torque and run a brief test of
my test objects. Here is my test source.
//////////////////////////////////////////////////////////////////
// Begin MyTest.java source
//////////////////////////////////////////////////////////////////
package com.digitalevergreen.mytest;
import com.digitalevergreen.mytest.om.*;
import org.apache.torque.Torque;
import org.apache.torque.util.Criteria;
import java.util.Vector;
public class MyTest
{
public static void main(String[] args)
{
try
{
// Initialze Torque
Torque.init( "./mytest.properties" );
// Create some Authors
Author de = new Author();
de.setFirstName( "David" );
de.setLastName( "Eddings" );
de.save();
Author tg = new Author();
tg.setFirstName( "Terry" );
tg.setLastName( "Goodkind" );
tg.save();
// Create publishers
Publisher b = new Publisher();
b.setName( "Ballantine" );
b.save();
Publisher t = new Publisher();
t.setName( "Tor" );
t.save();
// Ok. For some reason even though the BaseXPeer doInsert
// methods return the primary key it is not set in the
// BaseX save method so we have to "retrieve" these objects
// from the database or we will get null value exceptions
// when we try to use them in the book objects and do a
save.
Criteria crit = new Criteria();
crit.add( AuthorPeer.LAST_NAME, "Eddings" );
Vector v = AuthorPeer.doSelect( crit );
if ( v != null && v.size() > 0 )
de = (Author) v.elementAt(0);
crit = new Criteria();
crit.add( AuthorPeer.LAST_NAME, "Goodkind" );
v = AuthorPeer.doSelect( crit );
if ( v != null && v.size() > 0 )
tg = (Author) v.elementAt(0);
crit = new Criteria();
crit.add( PublisherPeer.NAME, "Ballantine" );
v = PublisherPeer.doSelect( crit );
if ( v != null && v.size() > 0 )
b = (Publisher) v.elementAt(0);
crit = new Criteria();
crit.add( PublisherPeer.NAME, "Tor" );
v = PublisherPeer.doSelect( crit );
if ( v != null && v.size() > 0 )
t = (Publisher) v.elementAt(0);
// Create books
Book wfr = new Book();
wfr.setTitle( "Wizards First Rule" );
wfr.setCopyright( "1994" );
wfr.setISBN( "0-812-54805-1" );
wfr.setPublisher( t );
wfr.setAuthor( tg );
wfr.save();
Book dof = new Book();
dof.setTitle( "Domes of Fire" );
dof.setCopyright( "1992" );
dof.setISBN( "0-345-38327-3" );
dof.setPublisher( b );
dof.setAuthor( de );
dof.save();
// Get and print books from db
crit = new Criteria();
v = BookPeer.doSelect( crit );
for ( int i = 0; i < v.size(); i++ )
{
Book book = (Book) v.elementAt(i);
System.out.println("Title: " + book.getTitle() );
System.out.println("Author: " +
book.getAuthor().getFirstName()
+ " " +
book.getAuthor().getLastName() );
System.out.println("Publisher: " +
book.getPublisher().getName() );
System.out.println("\n\n");
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
//////////////////////////////////////////////////////////////////
// End MyTest.java source
//////////////////////////////////////////////////////////////////
Step 7) Build the test app
----------------------------------------------------------
The ant configuration in torque should be set up to compile all the
source. This assumes that you put your MyTest.java in the
~/projects/torque/src directory tree. To build just do an ant compile.
> cd ~/projects/torque
> ant compile
This will place all the compiled class files under
~/projects/torque/bin/classes
Step 8) Run the test
----------------------------------------------------------
You need to have the torque/bin/classes directory in your classpath
along with all the jars in the torque/lib directory. You also
need to have the database driver in your classpath. I set my
classpath as follows:
>
CLASSPATH=~/projects/torque/lib/torque-1.0.jar:~/projects/torque/lib/com
mons-util-0.1-dev.jar:~/projects/torque/lib/commons-collections.jar:~/pr
ojects/torque/lib/jdbc2_0-stdext.jar:~/projects/torque/lib/log4j-1.1.jar
:~/projects/torque/lib/velocity-1.2-dev.jar:~/projects/torque/lib/villag
e-1.5.3-dev.jar:~/projects/torque/lib/xerces-1.3.0.jar:~/projects/torque
/lib/mysql_uncomp.jar:./bin/classes/; export CLASSPATH
Once this is set then run the MyTest.java main.
> cd ~/projects/torque
> java com.digitalevergreen.mytest.MyTest
You should see the following output:
> Title: Wizards First Rule
> Author: Terry Goodkind
> Publisher: Tor
>
>
>
> Title: Domes of Fire
> Author: David Eddings
> Publisher: Ballantine
Pretty simple, powerful, and cool once I figured it out.
Anyway thats how I got it to work. Anyone that has suggestions
for better ways to do it please let me know.
-- Steven F. Davis
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]