
Beginning Apache Struts - From Novice To Professional (2006)
.pdf368 A P P E N D I X A ■ F R A M E W O R K S F O R T H E M O D E L
public String getPassword(){ return _password;
}
public String setPassword(String password){ _password = password;
}
}
For each bean you want to persist using Hibernate, you have to create an XML description of it, which essentially maps the bean’s properties to tables and columns in your database. The XML mapping for User appears in Listing A-8.
Listing A-8. Hibernate XML Description of the User Bean
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="net.thinksquared.registration.data.User" table="user">
<id name="userId" type="string" unsaved-value="null">
<column name="user-id" sql-type="char(32)" not-null="true"/>
<generator class="assigned"/> </id>
<property name="password">
<column name="password" sql-type="char(32)" not-null="true"/>
</property>
</class> </hibernate-mapping>
A P P E N D I X A ■ F R A M E W O R K S F O R T H E M O D E L |
369 |
The XML is fairly self-explanatory, and I won’t describe it further in any detail. The essential idea is that you have an XML file that maps your bean to an existing table in the database.
Saving a bean from scratch is a simple three-step process, very similar to saving data with JDBC:
1.Initialize Hibernate.
2.Obtain a Session object.
3.Save the bean using the Session and close the Session.
Step 1 is usually performed once, when the application starts up. Listing A-9 illustrates steps 1 to 3.
Listing A-9. Saving a User Bean with Hibernate
User u = new User(); u.setUserId("kolmogorov"); u.setPassword("turbulence23");
//Step 0: Start Hibernate
Configuration config = new Configuration().addClass(User.class); SessionFactory factory = config.buildSessionFactory();
//Step 1: Get a Session
Session s = factory.openSession();
//Step 2: Save and close
Transaction t = s.beginTransaction(); s.save(u);
t.commit();
s.close();
Remember that the User class is not autogenerated by Hibernate—it’s assumed to be an existing class in your app. Hibernate’s job is to allow you to save instances of User to a database without you having to worry about SQL and databases.
Doing a search for an object is easy, too. Listing A-10 shows how to implement the exists() function to check whether a given user ID exists.
370 A P P E N D I X A ■ F R A M E W O R K S F O R T H E M O D E L
Listing A-10. An Implementation of exists() with Hibernate
public static boolean exists(String userId){
final String QUERY = "select u from u " +
"in class net.thinksquared.registration.data" + " where u.userId = :userId";
Session s = ... //Get a session somehow.
Query q = s.createQuery(QUERY);
try{
q.setString("userId",userId); List l = q.list();
return (l.size() > 0);
}finally{
s.close();
}
}
The QUERY string is an example of the Hibernate Query Language (HQL), which is similar to SQL except that it works for persisted objects.
These examples do not even begin to scratch the surface of Hibernate’s capabilities. But I hope I’ve given you at least some idea of how Hibernate is used.
In a Nutshell...
In this section I’ve provided a very brief overview of the major persistence frameworks, Hibernate and Torque. These frameworks are complex and whole books are devoted to them, so the treatment in this section is very much incomplete. Even so, I hope I’ve given you a good starting point for your own explorations into this area.
Autogenerating LILLDEP Model Classes
I’ve used Lisptorq to generate LILLDEP Model classes. The code for this is in the .\lisp\ subdirectory of the main LILLDEP development folder.
There are three database tables:
A P P E N D I X A ■ F R A M E W O R K S F O R T H E M O D E L |
371 |
•CONTACT, which stores contact information (see Lab 6)
•COLLECTION, which stores a collection’s name and notes
•COLLECTION_MAP, which stores the actual contacts that go into a collection
To use Lisptorq to generate these classes, you first create a LISP file describing the three tables, as in Listing A-11.
Listing A-11. models.lisp, the Lisptorq LISP File to Autogenerate LILLDEP Model Classes
(import lisptorq.lisp)
define database
(
(contact
(contact_id (PRIMARY REQUIRED INTEGER AUTO)) (name ((VARCHAR 1024)))
(designation ((VARCHAR 1024))) (department ((VARCHAR 1024))) (email ((VARCHAR 255)))
(tel ((VARCHAR 255))) (fax ((VARCHAR 255)))
(company ((VARCHAR 1024))) (address ((VARCHAR 1024))) (postcode ((VARCHAR 16)))
(website ((VARCHAR 255))) (activity ((VARCHAR 2048))) (classification ((VARCHAR 16))) (memo ((VARCHAR 2048)))
)
(collection
(collection_id (PRIMARY REQUIRED INTEGER AUTO)) (name ((VARCHAR 1024)))
(memo ((VARCHAR 2048)))
) |
|
(collection_map |
|
(collection_id |
(REQUIRED INTEGER (FOREIGN collection))) |
(contact_id |
(REQUIRED INTEGER (FOREIGN contact))) |
) |
|
)
372 A P P E N D I X A ■ F R A M E W O R K S F O R T H E M O D E L
(lisptorq:set database-name |
lilldep) |
(lisptorq:set database-type |
derby) |
(lisptorq:set derby-home |
./dbase) |
(lisptorq:set package |
net.thinksquared.lilldep.database) |
(lisptorq:generate database)
To autogenerate the Model classes from this definition, simply put the JAR files jlisp.jar and lisptorq.jar in your classpath, and call the Loader class, like so:
java -classpath jlisp.jar;lisptorq.jar net.thinksquared.jlisp.Loader models.lisp
This will generate all your Model and helper classes, including a DatabaseSetup class, which you can call to create the tables on the database. For a tutorial on using Lisptorq, see www.thinksquared.net/dev/lisptorq/.
Unfortunately, as for LILLDEP, we’ll have to use two different derby-homes: one when the database is initialized for the first time, and the other when it is deployed on Tomcat. This means that you’ve got to create the class twice, or manually change the static section that sets up derby-home in Database.java to that listed in Listing A-12.
Listing A-12. A Tweak to Database.java
//set path to database
String catalinaHome = System.getProperty("catalina.home"); if(catalinaHome == null){
//we are called from an pre-install program System.setProperty("derby.system.home","./dbase");
}else{
//we are on a Tomcat servlet System.setProperty("derby.system.home",
catalinaHome + "/webapps/lilldep/dbase");
}
A P P E N D I X A ■ F R A M E W O R K S F O R T H E M O D E L |
373 |
Useful Links
•The Derby project: http://incubator.apache.org/derby/
•For more on ACID: http://en.wikipedia.org/wiki/ACID
•Hibernate: www.hibernate.org/
•Torque: http://db.apache.org/torque/
•Lisptorq: www.thinksquared.net/dev/lisptorq/

A P P E N D I X B
■ ■ ■
Commonly Used Classes
This appendix describes selected servlet and Struts classes. Please note that not all functions on a class are shown—only the ones I believe you might find useful.
The documentation for the Struts classes (Action, ActionForm, ActionMessage,
ActionMessages, ActionError, ActionErrors, ActionMapping, FormFile, ComponentContext, and ExceptionHandler) has been adapted from Apache’s JavaDocs for those classes, and is reproduced here for your convenience under the Apache License. A copy of the Apache License is available at www.apache.org/licenses/LICENSE-2.0.
javax.servlet.http.HttpServletRequest
This class encapsulates an incoming HTTP request. It is used to store or retrieve objects that have request scope (using get/set/removeAttribute()). You may also store session scope objects on it by first using getSession() to acquire an HttpSession object (see the next section).
Return Type |
Function |
Comments |
Object |
getAttribute(String name) |
Returns the value of the named |
|
|
attribute as an Object, or null if no |
|
|
attribute of the given name exists |
void |
removeAttribute(String name) |
Removes an attribute from this |
|
|
request |
void |
setAttribute(String name,Object o) |
Stores an attribute in this request |
HttpSession |
getSession() |
Returns the current session asso- |
|
|
ciated with this request, or if the |
|
|
request does not have a session, |
|
|
creates one |
String |
getParameter(String name) |
Returns the value of a request |
|
|
parameter as a String, or null |
|
|
if the parameter does not exist |
|
|
|
375

376 |
A P P E N D I X B ■ C O M M O N L Y U S E D C L A S S E S |
javax.servlet.http.HttpSession
As its name implies, HttpSession is used to store session-scoped variables. It has get/set/ removeAttribute() functions, identical to HttpServletRequest.
Return Type |
Function |
Comments |
Object |
getAttribute(String name) |
Returns the object bound |
|
|
with the specified name |
|
|
in this session, or null if |
|
|
no object is bound under |
|
|
the name |
void |
removeAttribute(String name) |
Removes the object |
|
|
bound with the specified |
|
|
name from this session |
void |
setAttribute(String name, Object value) |
Binds an object to this |
|
|
session, using the name |
|
|
specified |
String |
getId() |
Returns a string |
|
|
containing the unique |
|
|
identifier assigned to this |
|
|
session |
|
|
|
org.apache.struts.action.ActionMessage
ActionMessage encapsulates a single locale-independent message. Only the constructors of ActionMessage are important to webapp developers.
Constructor |
Comments |
ActionMessage(String key)
ActionMessage(String key, Object value0)
ActionMessage(String key, Object[] values)
ActionMessage(String key, Object value0, Object value1)
ActionMessage(String key, Object value0, Object value1, Object value2)
ActionMessage(String key, Object value0, Object value1, Object value2, Object value3)
Constructs an action message with no replacement values
Constructs an action message with the specified replacement values
Constructs an action message with the specified replacement values
Constructs an action message with the specified replacement values
Constructs an action message with the specified replacement values
Constructs an action message with the specified replacement values
A P P E N D I X B ■ C O M M O N L Y U S E D C L A S S E S |
377 |
org.apache.struts.action.ActionMessages
This class is used to store multiple ActionMessages.
Return Type |
Function |
Comments |
void |
add(String property,ActionMessage message) |
Adds a message to the set |
|
|
of messages for the specified |
|
|
property |
boolean |
isEmpty() |
Returns true if there are no |
|
|
messages recorded in this |
|
|
collection, or false otherwise |
|
|
|
ActionMessages also has a static String variable called GLOBAL_MESSAGE, which is a property name marker to use for global messages (as opposed to those related to a specific property).
org.apache.struts.action.ActionErrors
ActionErrors is a subclass of ActionMessages, and its sole use is as the return value of ActionForm’s validate(). All of the functions and properties on this class have been deprecated. You should refer to functions or properties on ActionMessages instead.
org.apache.struts.action.ActionMapping
ActionMapping holds information about the valid “next” pages for a particular form handler.
Return Type |
Function |
Comments |
ActionForward |
findForward(String name) |
Finds and returns the ActionForward |
|
|
instance defining how forwarding to |
|
|
the specified logical name should be |
|
|
handled |
ActionForward |
getInputForward() |
Gets the context-relative path of the input |
|
|
form to which control should be returned |
|
|
if a validation error is encountered |
|
|
|
org.apache.struts.action.Action
An Action is an adapter between the contents of an incoming HTTP request and the corresponding business logic that should be executed to process this request. Struts will select an appropriate Action for each request, create an instance (if necessary), and call the