Stringer Framework Developer's Guide

helpflightInternet και Εφαρμογές Web

10 Νοε 2013 (πριν από 3 χρόνια και 7 μήνες)

99 εμφανίσεις













Struts2+Spring+Hibernate-like
Web Application Framework
Stringer Framework



Developer's Guide


Version 0.1.0





















Revised: February 2009

Stringer Framework
Developer's Guide

2


Contents

1 Overview..............................................................................................................................3
1.1 What is Stringer Framework?........................................................................................3
2 Installation...........................................................................................................................4
2.1 Prerequisites.................................................................................................................4
2.2 Downloading.................................................................................................................4
3 Getting Started.....................................................................................................................5
3.1 Run the sample.............................................................................................................5
3.2 Table schema................................................................................................................6
3.3 Entity class....................................................................................................................7
3.4 Service class.................................................................................................................8
3.5 Action class...................................................................................................................9
3.6 JSP page.....................................................................................................................10
3.7 web.xml........................................................................................................................11
3.8 hibernate.properties.....................................................................................................12
4 Use Interface for Transactional classes............................................................................13
4.1 Wrong Sample.............................................................................................................13
4.2 Solution 1: Use Interface..............................................................................................13
4.3 Solution 2: Define in applicationContext.xml.................................................................14
5 EntityManager vs HibernateTemplate................................................................................15
5.1 EntityManager (Java Persistence API)..........................................................................15
5.2 HibernateTemplate.......................................................................................................16
6 1-to-N Relationship (Transaction sample).........................................................................18
6.1 Run the sample............................................................................................................18
6.2 Table schema...............................................................................................................20
6.3 Entity class...................................................................................................................20
6.4 Service class................................................................................................................22
7 Interceptor...........................................................................................................................25
7.1 Interceptor class...........................................................................................................25
7.2 Register the interceptors...............................................................................................26
8 How to switch to real frameworks......................................................................................28
8.1 Downloading and gathering required jars......................................................................28
8.2 EntityManager..............................................................................................................29
8.2.1 stringerx package name...........................................................................................30
8.2.2 web.xml...................................................................................................................31
8.2.3 taglib in JSPs...........................................................................................................32
8.2.4 applicationContext.xml.............................................................................................33
8.2.5 persistence.xml........................................................................................................34
8.2.6 struts.xml.................................................................................................................34
8.3 HibernateTemplate.......................................................................................................35
8.3.1 stringerx package name...........................................................................................35
8.3.2 web.xml...................................................................................................................35
8.3.3 taglib in JSPs...........................................................................................................36
8.3.4 hibernate.properties.................................................................................................36
8.3.5 applicationContext.xml.............................................................................................36
8.3.6 struts.xml.................................................................................................................37
9 Supported Functions..........................................................................................................38
9.1 Struts2.........................................................................................................................38
9.2 Spring 2.5.....................................................................................................................38
9.3 Hibernate 3..................................................................................................................39


Stringer Framework
Developer's Guide

3


1 Overview
This document is for developers who are starting to learn Java Web Application Development.

1.1 What is Stringer Framework?
The Stringer Framework (“Stringer”) is another implementation of St
ruts2, Spring
Framework
and Hiber
nate, and provides limited functions that we really need to learn the frameworks, for
example, action invocation, declarative transaction (@Transactional), autowiring
(@Autowired), persistent objects using JPA (Java Persistence API). If you are already
familiar to the frameworks, you could see same coding style in the following sample code.
But the Stringer doesn’t require the real libraries because it has own implementation
according to the API interface of the real ones.
The Stringer is a 3 in 1 framework providing Web MVC, DI container and O-R mapping,
however, it’s very compact (the size of jar file is less than 200KB) so that you can fully read
the source code and understand the cause of errors when you encounter problems.
The source code developed with Stringer can be compiled with the real frameworks with
package name changes (e.g. rename stringerx.hibernate to org.hibernate). Basically, the
Stringer doesn't guarantee 100% compatibility, but it should be able to run with a few
changes.
The Stringer enables you to easily start your learning on web development with fewer
configurations.

IMPORTANT: Once you get ideas how to develop with Struts2+Spring+Hibernate style,
please switch to real frameworks; Struts2, Spring Framework and Hibernate.

Sample code of a service class developed with the Stringer:
@Service
public class TransactionServiceImpl implements TransactionService {

@PersistenceContext
private EntityManager entityManager = null;

public TransactionServiceImpl() {
}

@Transactional(propagation=Propagation.REQUIRED)
public void insert(String name, int age, String[] addresses)
throws Exception {
Directory d = new Directory();
d.setName(name);
d.setAge(age);
d.setCreatedDate(new Timestamp(new Date().getTime()));
entityManager.persist(d);

int userId = d.getId();

for (String address: addresses) {
insertAddress(userId, address);
}
}



Stringer Framework
Developer's Guide

4


2 Installation

2.1 Prerequisites
Before starting to install, you need to install or download the following software:

 JDK Version 5.x or 6.x

 Apache Tomcat Version 6.x
It must also work on other servlet containers that implement the Servlet 2.4 and
JavaServer Pages 2.0, but we tested on the Tomcat only.

 Apache Ant Version 1.7.x
This is required to make a build.

The following are the required jars, which are contained in stringer-<version>.zip.

JAR
Description
Required
Required


commons-logging-
1.1.1.jar
Apache Commons Logging Yes
log4j-1.2.15.jar Apache Log4J Yes
common-
annotations.jar
Java Common Annotations
(from Spring Framework v2.5.5)

Yes
persistence.jar Java Persistence Annotations
(from Spring Framework v2.5.5)

Yes
javassist.jar Javassist v3.9.0 Yes
Optional


hsqldb.jar HSQLDB v1.8.0.10 Yes if you use HSQLDB

mysql-connector-java-
5.1.7-bin.jar
MySQL JDBC Drivers
v5.1.7
Yes if you use MySQL
ojdbc14.jar Oracle Database 10g JDBC
Drivers
Yes if you use Oracle
jstl.jar and standard.jar Java Standard Tag Libraries
(JSTL)
No


2.2 Downloading
Download the latest version of Stringer Framework (stringer-<version>.zip) from the site
below:

http://www5f.beglobe.ne.jp/~webtest/stringer/


Stringer Framework
Developer's Guide

5


3 Getting Started
To understand how to develop a web application, which accesses database, with
struts2+Spring+Hibernate, let’s take a look at a “simple” sample in the downloaded zip file.

3.1 Run the sample
Before going through the code, deploy the sample on Tomcat and access the pages to see
how the sample works.

1. Unzip the stringer-<version>.zip downloaded
2. Go to the <STRINGER-HOME> where you unzipped.
3. Open “build.properties” and change “tomcat.home” to your TOMCAT-HOME location.


## TOMCAT
tomcat.home=/apache-tomcat-6.0.18
tomcat.work=${tomcat.home}/work/Catalina/localhost

4. Go to <STRINGER-HOME>/samples/simple/.
5. Run “ant createTables” task from command line.
(simple-db.properties and simple-db.script files will be generated under your
${tomcat.home}/bin directory)

C> ant createTables

6. Run “ant deploy” task from command line.
(simple.war will be generated under build and deployed in ${tomcat.home}/webapps)

C> ant deploy

7. Start your Tomcat.
8. Access http://localhost:8080/simple with your browser.




9. Enter your name and age. And click on Add.
You will see the name and age entered in the table.



Stringer Framework
Developer's Guide

6


3.2 Table schema
First, you need to define table schema. In this sample, we need to store name and age that
user entered. Also, created date and unique ID are necessary to handle each record. This
sample defines the “Directory” table containing the following columns:

Column Name
Description
Type
ID Unique ID (Primary Key) INTEGER
NAME Name VARCHAR(100)
AGE Age INTEGER
CREATED_DATE Date and time when the record is
inserted.
TIMESTAMP

Also, DIRECTORY_SEQ sequence is required to generate unique ID. Below is the schema
defined in <STRINGER-HOME>/samples/simple/db/hsqldb.sql

-------------------------------
-- Create sequence
-------------------------------
DROP SEQUENCE DIRECTORY_SEQ IF EXISTS;
CREATE SEQUENCE DIRECTORY_SEQ START WITH 1 INCREMENT BY 1;

-------------------------------
-- Create table
-------------------------------
DROP TABLE DIRECTORY IF EXISTS;

CREATE TABLE DIRECTORY(
ID INTEGER PRIMARY KEY
,NAME VARCHAR(100) NOT NULL
,AGE INTEGER
,CREATED_DATE TIMESTAMP NOT NULL
);

COMMIT;

SHUTDOWN;

Stringer Framework
Developer's Guide

7


3.3 Entity class
Next, you need to create an entity Java class to store a record in Directory table.

@Entity
public class Directory implements Serializable {
private static final long serialVersionUID = -8897698852895650771L;

private int id = 0;
private String name = null;
private int age = 0;
private Timestamp createdDate = null;

@Id
@GeneratedValue(strategy=GenerationType.AUTO, generator="gen_id")
@SequenceGenerator(name="gen_id", sequenceName="DIRECTORY_SEQ")
public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

@Column
public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Column
public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

@Column(name="CREATED_DATE")
public Timestamp getCreatedDate() {
return createdDate;
}

public void setCreatedDate(Timestamp createdDate) {
this.createdDate = createdDate;
}


In the getter method for primary key, in this case getId(), @Id has to be specified. Also, you
need to define sequence name using @GeneratedValue and @SequenceGenerator.
Stringer Framework
Developer's Guide

8

Other getter methods are mapped to each table column. If the property name is different from
the table column name, you can specify column name using @Column(name=”<column-
name>”) anottation.

3.4 Service class
Service class is a class to implement business logic, which is called by action class.
SimpleService provides two features below:

 void insert(final String name, final int age)
Insert a new record into Directory table.
 List getAll()
Retrieve all records and return List object containing the records.

@Service
public class SimpleService {

@Autowired
private HibernateTemplate hibernateTemplate;

public SimpleService() {
}

public void insert(String name, int age) throws Exception {
Directory d = new Directory();
d.setName(name);
d.setAge(age);
d.setCreatedDate(new Timestamp(new Date().getTime()));
hibernateTemplate.save(d);
}

public List getAll() throws Exception {
DetachedCriteria criteria =
DetachedCriteria.forClass(Directory.class)
.addOrder(desc("createdDate"));
return hibernateTemplate.findByCriteria(criteria);
}

}

@Service represents that this class is a service class. Next, @Autowired is marked in
HibernateTemplate field. So, when this object is instantiated, HibernateTemplate instance,
which implements operations to save, update, delete object using Hibernate session internally,
is injected into this field.
The insert method generates a Directory object with the given name and age and save it in
database. The getAll method retrieves all records sorted by ID column from bigger number.


Stringer Framework
Developer's Guide

9


3.5 Action class
Action is a class to handle a request sent by user. The framework populates the values in
request into properties of this action and invoke execute method. After the execution, the
properties updated are set into the request object and passed to JSP. Since the properties are
set in request attributes, you can simply access the value using EL in the JSP, e.g. ${name}.

@Results({
@Result(name=Action.SUCCESS, value = "/index.jsp")
,@Result(name=Action.ERROR, value = "/error.jsp")
})
public class SimpleAction {
private String name = null;
private int age = 0;
private List directory = null;

@Autowired
private SimpleService simpleService = null;

public String execute() {
if (name == null || name.trim().length() == 0 || age < 0) {
return ERROR;
}

try {
simpleService.insert(name, age);
directory = simpleService.getAll();
} catch (Exception ex) {
ex.printStackTrace();
return ERROR;
}

return Action.SUCCESS;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}


JSP file to be used is defined by @Results and @Result annotations and determined by the
return value of execute method. If it’s “success” (Action.SUCCESS), the request is forwarded
to /index.jsp.
To retrieve data from database, methods in SimpleService are called in this action. The
instance is automatically injected by @Autowired annotation when this action is instantiated.

Stringer Framework
Developer's Guide

10


3.6 JSP page
The properties defined in action are set in request attributes, so you can simply access the
values using EL in the JSP, e.g. ${name}.

war/error.jsp

Name and age are required to add into the directory.<br>
<br>
name=(${name})<br>
age=(${age})<br>


If you need to control the values using, for example, loop, use JSTL.

war/index.jsp

<s:form action="simple">
Name: <s:textfield name="name" value="" size="20"/>&nbsp;
Age: <s:textfield name="age" value="" size="3"/>&nbsp;
<s:submit name="add" value="Add"/>
</s:form>
<br>

<table border="1">
<tr><th>Name</th><th>Age</th><th>Created Date</th></tr>
<c:forEach var="dir" items="${directory}">
<tr><td>${dir.name}</td><td>${dir.age}</td><td>${dir.createdDate}</td></tr>
</c:forEach>
</table>



Stringer Framework
Developer's Guide

11


3.7 web.xml
To capture user requests, you also need to add the following entries in web.xml.

war/WEB-INF/web.xml

<filter>
<filter-name>Stringer</filter-name>
<filter-class>stringerx.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<init-param>
<param-name>actionPackages</param-name>
<param-value>stringer.samples.simple.action</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>Stringer</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<listener>
<listener-class>
stringerx.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>


Add FilterDispatcher filter and the mapping. In the filter definition, you need to specify
actionPackages parameter with you action package path.


Stringer Framework
Developer's Guide

12


3.8 hibernate.properties
JDBC connection settings are defined in hibernate.properties file.

src/hibernate.properties
hibernate.connection.driver_class=org.hsqldb.jdbcDriver
hibernate.connection.url=jdbc:hsqldb:file:simple-db;shutdown=true
hibernate.connection.username=sa
hibernate.connection.password=

hibernate.dialect=org.hibernate.dialect.HSQLDialect
hibernate.show_sql=true



In this sample, service and HbernateTemplate are injected by @Autowired with default settings, so
you don’t have to specify any settings for ApplicationContext for DI container. If you want to create
non-singleton object (prototype model) or create object by name (bean ID) using @Qualifier
annotation, you need to create ApplicationContext.xml file and configure the beans.












The key point of this sample is to understand what values and objects are automatically populated.
First, MVC framework populates request values into action object. And after executing the action,
the action properties are set back to the request object. Also, the MVC creates the action object
using DI container, so fields and method parameters defined with @Autowired are injected
appropriate object according to the class type. In this case, SimpleService is injected into the action.
The service is also defined @Autowired for HibernateTemplate, the object is injected into the
service when the service is instantiated.
Some SQL queries are executed in HibernateTemplate. The result set is populated into Directory
object by O/R mapping framework.


<<Action>>
Simple
<<Service>>

Simple
<<Entity>>

Directory
Hibernate
Template
Request

@Autowired
@Autowired
properties
Stringer Framework
Developer's Guide

13


4 Use Interface for Transactional classes

IMPORTANT: If you use declarative transaction (@Transactional annotation), we
strongly recommend using interface for the concrete class or defining the class in
applicationContext.xml. Otherwise, transactional code may NOT be injected (Your
queries are executed in a non-transaction session).


4.1 Wrong Sample
Below is a wrong sample. The code itself is no problem, but transactional code may not be
injected, because the default class loader may load before loading by Stringer.
Let’s say that you created a TransactionBean class defined a transactional method,
saveUserProfile.

public class TransactionBean {

@Autowired
private HibernateTemplate hibernateTemplate;

public TransactionBean() {
}

@Transactional(propagation=Propagation.REQUIRED)
public void saveUserProfile(User user, Address addr) throws Exception {
saveUser(user);
saveAddress(addr);
}


If another client code has already created the class using “new” or something, the class was
loaded by default class loader. In this case, no one can modify the class. So, Stringer will fail to
inject transaction code to begin & end transaction and commit or roll back.

public class Client {

TransactionBean tranBean = new TransactionBean();



4.2 Solution 1: Use Interface
In order to enable the transaction, create interface below:

public interface TransactonBean {

public void saveUserProfile(User user, Address addr) throws Exception;

}

Then rename the original class to interface name + “Impl” and implements the interface.

public class TransactionBeanImpl implements TransactionBean {
Stringer Framework
Developer's Guide

14


@Autowired
private HibernateTemplate hibernateTemplate;

public TransactionBean() {
}

@Transactional(propagation=Propagation.REQUIRED)
public void saveUserProfile(User user, Address addr) throws Exception {
saveUser(user);
saveAddress(addr);
}


With this change, default class loader only loads the interface, and the concrete class is not
loaded. So, the Stringer can inject transactional code into the TransactionBeanImpl class.


Use different concrete class name:

If you want to use different class name for the concrete class (in this case,
TransactionBeanImpl to DefaultTransactionBean), define the class using bean tag in
applicationContext.xml file.

<bean id=”transactionBean” class=”myapp.service.DefaultTransactionBean” />

Then, specify the bean ID (transactionBean) in @Qualifier annotation in your Java code.

public class Client {

@Autowired
@Qualifier("transactionBean")
private TransactionBean tranBean = null;



4.3 Solution 2: Define in applicationContext.xml
If you don’t want to create an interface, you can solve the issue by defining the bean in
applicationContext.xml. The classes of the bean registered in the XML are loaded by Stringer
when servlet contaner is started, so the class should be loaded by Stringer, not default class
loader.

<bean id=”transactionBean” class=”myapp.service.TransactionBean” />


Stringer Framework
Developer's Guide

15


5 EntityManager vs HibernateTemplate
The real frameworks, Spring and Hibernate, provides us various ways to persist objects into
database. The Stringer only supports EntityManager (Java Persistent API) and
HibernateTemplate (Hibernate classic style). Please refer to Reference document for the detail
in terms of supported APIs in the Stringer.
The reason is why the Stringer supports the two interfaces is that there are pros and cons in
both ways. This chapter shows what are the advantages or disadvantages to use for each
interface.


5.1 EntityManager (Java Persistence API)
The Stringer implements EntityManager in Java Persistence API, which is standard
persistence API. Using EntityManager is recommended rather than using HibernateTemplate.
Here is the sample code to persist and retrieve data.

EntityManager:

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Service
public class SimpleService {

@PersistenceContext
private EntityManager entityManager = null;

public SimpleService() {
}

public void insert(String name, int age) throws Exception {
Directory d = new Directory();
d.setName(name);
d.setAge(age);
d.setCreatedDate(new Timestamp(new Date().getTime()));
entityManager.persist(d);
}

public List getAll() throws Exception {
Session session = (Session) entityManager.getDelegate();
return session.createCriteria(Directory.class)
.addOrder(desc("createdDate"))
.list();
}
}

The EntityManager instantiates a Session object internally, and allows you to obtain the
Session object if you want. So, you can easily execute full Hibernate Session APIs. The
session is automatically closed at the end of each method.

Stringer Framework
Developer's Guide

16


5.2 HibernateTemplate
The HibernateTemplate is a helper class for executing queries in Spring integrated with
Hibernate. Here is the sample code doing the same process as the EntityManager sample.

HibenateTemplate:

import stringerx.hibernate.criterion.DetachedCriteria;
import stringerx.springframework.beans.factory.annotation.Autowired;
import stringerx.springframework.orm.hibernate3.HibernateTemplate;

@Service
public class SimpleService {

@Autowired
private HibernateTemplate hibernateTemplate = null;

public SimpleService() {
}

public void insert(String name, int age) throws Exception {
Directory d = new Directory();
d.setName(name);
d.setAge(age);
d.setCreatedDate(new Timestamp(new Date().getTime()));
hibernateTemplate.save(d);
}

public List getAll() throws Exception {
DetachedCriteria criteria =
DetachedCriteria.forClass(Directory.class)
.addOrder(desc("createdDate"));
return hibernateTemplate.findByCriteria(criteria);
}
}

The HibernateTemplate also instantiates a Session object internally. At the end of the
execution of the method, the connection is automatically closed.
The session is not created before executing HibernateTemplate APIs, so you cannot use
Criteria object to retrieve data. Instead, use DetachedCriteria and pass it to the
HibernateTemplate.
If you want to use obtain the Session object to fully control the session, you need to use
HibernateCallback interface as show below:

HibernateTemplate with a HibernateCallback:

@Service
public class CallbackService {

@Autowired
private HibernateTemplate hibernateTemplate = null;

public List getAll() throws Exception {
HibernateCallback cb = new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
Stringer Framework
Developer's Guide

17

return session.createCriteria(Bean.class)
.addOrder(asc(“id”))
.list();
}
};
return hibernateTemplate.execute(cb);
}
}



The session can be obtained in
HibernateCallback only.
Stringer Framework
Developer's Guide

18


6 1-to-N Relationship (Transaction sample)
The Stringer O/R mapping only supports 1-to-1 relationship. So, if you need to make a 1-to-N
(1-to-Many) relation, please use real Hibernate with Struts2 and Spring.
If you still want to use the Stringer and don’t mind to add a little code in your service classes to
associate entity objects, take a look at a “Transaction” sample that implements a 1-to-N
relationship. This chapter explains how the sample makes the relation using the Stringer.


6.1 Run the sample
The Transaction sample is very similar to the “Simple” sample explained in “Getting Started”
chapter. The difference is that the Transaction has two tables to store multiple addresses for
each user.
Before going through the code, deploy the sample on Tomcat and access the pages to see
how the sample works.

1. Go to <STRINGER-HOME>/samples/transaction/.
2. Run “ant createTables” task from command line.
(transaction-db.properties and transaction-db.script files will be generated under your
${tomcat.home}/bin directory)

C> ant createTables

3. Run “ant deploy” task from command line.
(transaction.war will be generated under build and deployed in ${tomcat.home}/webapps)

C> ant deploy

4. Start your Tomcat.
5. Access http://localhost:8080/transaction with your browser, and enter name, age and
address 1 only. (Keep “Address 2” blank this time). Then click on Add.




Stringer Framework
Developer's Guide

19


You will see the application error page below because of no Address 2 information.



6. Go back to previous page (using browser back button).
7. Enter all information including Address 2 and click on Add.
You will see the information entered in the table under the form.




Stringer Framework
Developer's Guide

20


6.2 Table schema
In this sample, there are two tables to store addresses as well as user information.










The user information, name and age, is stored in the DIRECTORY table but addresses are
stored in ADDRESS table with the user ID, because this sample requires users to enter
multiple address lines per user.
Below is a DDL for creating the tables. You can find the whole code in <STRINGER-
HOME>/samples/transaction/db/hsqldb.sql

CREATE TABLE DIRECTORY(
ID INTEGER PRIMARY KEY
,NAME VARCHAR(100) NOT NULL
,AGE INTEGER
,CREATED_DATE TIMESTAMP NOT NULL
);

CREATE TABLE ADDRESS(
ID INTEGER PRIMARY KEY
,USER_ID INTEGER NOT NULL
,ADDRESS VARCHAR(100) NOT NULL
,CREATED_DATE TIMESTAMP NOT NULL
);



6.3 Entity class
The Directory entity class looks same as the Directory class in the simple sample. But there is
an additional property named “addresses” in order to store address entities.
As a default, all properties are mapped to the table column, so you need to annotate
@Transient on the getter method not to persist the adresses object.

@Entity
public class Directory implements Serializable {
private static final long serialVersionUID = 3857056236497093495L;

private int id = 0;
private String name = null;
private int age = 0;
private Timestamp createdDate = null;
private List<Address> addresses = null;

@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="gen_id")
@SequenceGenerator(name="gen_id", sequenceName="DIRECTORY_SEQ")
<<Table>>
DIRECTORY

ID
NAME
AGE
CREATED_DATE
<<Table>>
ADDRESS

ID
USER_ID
ADDRESS
CREATED_DATE
1 0:n
Stringer Framework
Developer's Guide

21

public int getId() {
return id;
}



public void setCreatedDate(Timestamp createdDate) {
this.createdDate = createdDate;
}

@Transient
public List<Address> getAddresses() {
return addresses;
}

public void setAddresses(List<Address> addresses) {
this.addresses = addresses;
}


The Address entity class is a regular entity class. You need to simply define properties to be
mapped to the columns in the ADDRESS table.

@Entity
public class Address implements Serializable {
private static final long serialVersionUID = 8862714496922465941L;

private int id = 0;
private int userId = 0;
private String address = null;
private Timestamp createdDate = null;

@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="gen_id")
@SequenceGenerator(name="gen_id", sequenceName="ADDRESS_SEQ")
public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

@Column(name="USER_ID")
public int getUserId() {
return userId;
}

public void setUserId(int userId) {
this.userId = userId;
}

@Column
public String getAddress() {
return address;
}
Stringer Framework
Developer's Guide

22


public void setAddress(String address) {
this.address = address;
}

@Column(name="CREATED_DATE")
public Timestamp getCreatedDate() {
return createdDate;
}

public void setCreatedDate(Timestamp createdDate) {
this.createdDate = createdDate;
}




6.4 Service class
To store the user (name and age) and address information into DIRECTORY and ADDRESS
table, you need to execute the queries in a transaction for the data consistency. For example,
if an error occurred when storing into ADDRESS table after the user info has inserted into
DIRECTORY table, the user info has to be rolled back. Otherwise, the user information without
address info, which is an invalid data, will be stored into the DIRECTORY table.
So, the Transaction sample uses @Transactional for storing user and address objects.

As you can see in the “Use Interface for Transactional classes” chapter, the service class
using declarative transaction should define Interface to enable the Stringer to inject
transactional code.

public interface TransactionService {

public void insert(final String name, final int age, final String[] addresses)
throws Exception;

public void insertAddress(final int userId, final String address)
throws DataAccessException, HibernateException;

public List getAll() throws Exception;

}

Next, implement the interface in a concrete class (in this sample, TransactionServiceImpl).
The insert method saves the user name and age by calling save method of
HibernateTemplate. After that, it saves addresses by calling insertAddress method that also
calls HibernateTemplate.save to save an address object.
These two methods must be executed in a same transaction, so you can specify
Propagation.REQUIRED strategy in the @Transactionl annotation. However,
Propergation.SUPPORTS is defined on the insertAddress. (The SUPPORTS strategy only
executes in a transaction if a transaction already exists. Otherwise, it is executed with a non-
transactional mode.) This is because we don’t want to use transaction for the insertAddress
method if it is called by another method that simply wants to update an address.
Transactional method is costly in its execution. If there is only one query to update data in the
process, you should not use transaction. If you specify Propagation.REQUIRED on the
insertAddress, transaction will start even if you call the method only, and it takes longer time
Stringer Framework
Developer's Guide

23

than non-transactional execution. In this scenario, the insertAddress has to be in a transaction
only called by transactional method such as insert method.

public class TransactionServiceImpl implements TransactionService {

@Autowired
private HibernateTemplate hibernateTemplate;

public TransactionServiceImpl() {
}

@Transactional(propagation=Propagation.REQUIRED)
public void insert(String name, int age, String[] addresses) throws Exception {
Directory d = new Directory();
d.setName(name);
d.setAge(age);
d.setCreatedDate(new Timestamp(new Date().getTime()));
hibernateTemplate.save(d);

int userId = d.getId();

for (String address: addresses) {
insertAddress(userId, address);
}
}

@Transactional(propagation=Propagation.SUPPORTS)
public void insertAddress(int userId, String address)
throws DataAccessException {
if (address == null || address.trim().length() == 0) {
throw new DataRetrievalFailureException(
"Address must be described!!");
}

Address a = new Address();
a.setUserId(userId);
a.setAddress(address);
a.setCreatedDate(new Timestamp(new Date().getTime()));
hibernateTemplate.save(a);
}

@SuppressWarnings("unchecked")
public List getAll() throws Exception {
DetachedCriteria criteria;

criteria = DetachedCriteria.forClass(Directory.class)
.addOrder(desc("createdDate"));
List<Directory> dirs = (List<Directory>)
hibernateTemplate.findByCriteria(criteria);

for (Directory d: dirs) {
criteria = DetachedCriteria.forClass(Address.class)
.add(eq("userId", d.getId()));
List<Address> addrs = (List<Address>)
hibernateTemplate.findByCriteria(criteria);
d.setAddresses(addrs);
Stringer Framework
Developer's Guide

24

}

return dirs;
}

}

With the Stringer, Addresses entity objects are not injected into the Directory object, so you
need to retrieve address objects for each user in getAll method.


Stringer Framework
Developer's Guide

25


7 Interceptor
The Stringer provides you a way to intercept before and after an action execution. There is a
stack, which is a set of interceptors, in front of the action. They are invoked before executing
the action. With interceptors, you can encapsulate common functionality and apply it to multiple
actions.

7.1 Interceptor class
To intercept an action, you need to create an interceptor class that implements the following
Interceptor interface.

public interface Interceptor extends Serializable {

public void init();

public void destroy();

public String intercept(ActionInvocation invocation) throws Exception;

}

Or you can extend from the AbstractInterceptor that init and destroy are implemented.

The init method is invoked when instantiating the object. The destroy method is never called in
Stringer. The interceptor method is called before executing the action.
Below is a sample Interceptor class implementing the Interceptor interface.

public class TestInterceptor implements Interceptor {

public void init() {
System.out.println("[Test interceptor] init");
}

public void destroy() {
System.out.println("[Test interceptor] destroy (never called)");
}

public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("[Test interceptor] before invoke");
String result = invocation.invoke();
System.out.println("[Test interceptor] after invoke: result=("+result+")");
return result;
}

}

If you create a class extending from AbstractInterceptor, you don’t have to defind init and
destroy methods.

public class TestInterceptor extends AbstractInterceptor {

@Override
public String intercept(ActionInvocation invocation) throws Exception {
Stringer Framework
Developer's Guide

26

System.out.println("[Test interceptor] before invoke");
String result = invocation.invoke();
System.out.println("[Test interceptor] after invoke: result=("+result+")");
return result;
}

}

NOTE: The Stringer creates the Interceptor object using its DI container. So, you can use
Spring and JPA annotations (e.g. @Autowired, @ PostConstruct, @PersistenceContext, etc.)
in it. Whether it is instantiated as singleton or prototype depends on the settings in the
accplicationContext.xml. If you define the bean scope as singleton, it is created as singleton
object.

/WEB-INF/applicationContext.xml

<bean id="testInterceptor1" class="test.TestInterceptor1" scope="singleton" />

<bean id="testInterceptor2" class="test.TestInterceptor2" scope="prototype" />

However, if you use real struts2 and spring, all interceptors are instantiated as
singleton even if you specify prototype in the scope attribute.


7.2 Register the interceptors
Once you create your interceptor, register it in struts.xml file.

/WEB-INF/classes/struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>

<package name="testPackage" namespace="" extends="struts-default">

<interceptors>
<interceptor name="test1" class="test.TestInterceptor1" />
<interceptor name="test2" class="test.TestInterceptor2" />

<interceptor-stack name="testDefaultStack">
<interceptor-ref name="test1" />
<interceptor-ref name="test2" />
<interceptor-ref name="defaultStack" />
</interceptor-stack>
</interceptors>

<default-interceptor-ref name="testDefaultStack" />

</package>

</struts>

First, you need to define your interceptor class (TestInterceptor1 and 2 in this sample) using
interceptor tag under interceptors tag. Next, define interceptor-stack using the interceptor
Stringer Framework
Developer's Guide

27

names you defined. Stringer doesn’t have a defaultStack, but you can add the defaultStack for
compatibility with real Struts2 (Stringer ignores the defaultStack). Finally, replace the default
interceptor with the stack name you defined using default-interceptor-ref tag.
With the settings, the TestInterceptor1 and 2 are executed before invoking all actions in the
package.

If you want to assign to a specific action, define interceptor-ref tag in the action tag.


<package name="testPackage" namespace="" extends="struts-default">

<interceptors>
<interceptor name="test1" class="test.TestInterceptor1" />
<interceptor name="test2" class="test.TestInterceptor2" />
<interceptor name="test3" class="test.TestInterceptor3" />

<interceptor-stack name="testDefaultStack">
<interceptor-ref name="test1" />
<interceptor-ref name="test2" />
<interceptor-ref name="defaultStack" />
</interceptor-stack>
</interceptors>

<default-interceptor-ref name="testDefaultStack" />

<action name="test" class="test.TestAction">
<interceptor-ref name="test3" />
<result name="success">/target.jsp</result>
</action>
</package>

</struts>

In this sample, only TestInterceptor3 is called when executing TestAction (default interceptors
are not executed)

NOTE: Stringer properly picks actions defined in struts.xml for actions under actionPackages
(defined in web.xml) as well. However, real Struts2 doesn’t assign the interceptors in
struts.xml to the actions that locate under the actionPackages directory. To avoid the
conversion problems, we recommend not defining package including the actions that you want
to assign interceptors.

/WEB-INF/web.xml

<filter>
<filter-name>Stringer</filter-name>
<filter-class>stringerx.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<init-param>
<param-name>actionPackages</param-name>
<param-value>dummy</param-value>
</init-param>
</filter>


Stringer Framework
Developer's Guide

28


8 How to switch to real frameworks
The Stringer is supposed to be use for your personal learning only. Once you understand how
it works, you MUST use real frameworks, Struts2, Spring Framework and Hibernate.

8.1 Downloading and gathering required jars
1. Download Apache Struts2 from the site below:

http://struts.apache.org/

2. Download Spring Framework 2.5.x from the site below:

http://www.springsource.org/download

3. Download Hibernate Annotations 3.x and Hibernate EntityManager 3.x from the site
below:

http://www.hibernate.org/

4. Gather the required jar files from the downloaded files. Below is a sample jars with the
specific versions:

From Struts 2.1.6:


 commons-fileupload-1.2.1.jar
 commons-logging-1.0.4.jar
 freemarker-2.3.13.jar
 ognl-2.6.11.jar
 struts2-codebehind-plugin-2.1.6.jar
 struts2-core-2.1.6.jar
 struts2-spring-plugin-2.1.6.jar
 xwork-2.1.2.jar


From Spring Framework 2.5.5:


 spring.jar


From Hibernate Annotations 3.4.0:


 hibernate-annotations.jar
 dom4j.jar
 ejb3-persistence.jar
 hibernate-commons-annotations.jar
 hibernate-core.jar
 slf4j-api.jar
 antlr.jar
 asm.jar
 asm-attrs.jar
 commons-collections.jar
 javassist.jar
Stringer Framework
Developer's Guide

29

 jta.jar
 log4j.jar
 slf4j-log4j12.jar

From Hibernate EntityManager 3.4.0:


 hibernate-entitymanager.jar


In this chapter, we use <REAL-LIB> to represent the location you put the above jar files.

NOTE:
With Stringer, you can use same configurations for both persistence APIs (EntityManager and
HibernateTemplate), but real frameworks requires different configurations. Refer to
EntityManager or HibernateTemplate section depending on which APIs you used in your site.


8.2 EntityManager
EntityManager doesn’t work with HSQLDB, so we use tranmysql sample, which accesses
MySQL database, for this sample.
First, let’s start with compiling and running the sample code.

1. Go to <STRINGER-HOME>/samples/tranmysql/
2. If you don’t’ create tables yet, run “ant createTables” task.
3. If you don’t’ make the “tranmysql” build, run “ant compile” task.
4. Go to <STRINGER-HOME>/samples/tranmysql_real/
5. Open build.properties file with your favorite text editor
6. Set “lib.real” property to <REAL-LIB> where you put required jar files.

## Libraries of Struts2, Spring and Hibernate
lib.real=/home/frameworks/lib

7. Run “ant convert” task from the command line.
(The converted files will be generated in src and war directories)
And you will see the message below on the console.

[echo]
[echo] Insert the following entries in your war/WEB-INF/web.xml
[echo]
[echo] <filter>
[echo] <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
[echo] <filter-class>
[echo] org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
[echo] </filter-class>
[echo] </filter>
[echo]
[echo] <filter-mapping>
[echo] <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
[echo] <url-pattern>/*</url-pattern>
[echo] </filter-mapping>
[echo]

8. Open war/WEB-INF/web.xml and add the entries in the XML.

Stringer Framework
Developer's Guide

30

<filter>
<filter-name>Stringer</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<init-param>
<param-name>actionPackages</param-name>
<param-value>stringer.samples.transaction.action</param-value>
</init-param>
</filter>

<filter>
<filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
<filter-class>
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
</filter-class>
</filter>

<filter-mapping>
<filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
<filter-name>Stringer</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

9. Run “ant deploy” task from the command line.
10. Start Tomcat and access the URL below:

http://localhost:8080/tranmysql-real/

You will see same page as you saw on “transaction” application with Stringer, but it is running
with Struts2, Spring and Hibernate jar files (without Stringer jar)

Below are the explanations what to change for switching to real frameworks:

8.2.1 stringerx package name
The stringerx packages represent Struts2, Spring or Hibernate packages, so you need to
rename the package names to original name.

 stringerx.apache.struts2. ￿ org.apache.struts2.
 stringerx.springframework. ￿ org.springframework.
 stringerx.hibernate. ￿ org.hibernate.
 stringerx.opensymphony. ￿ com.opensymphony.

For example,

package stringer.samples.simple.action;
Stringer Framework
Developer's Guide

31


import java.util.List;
import stringerx.apache.struts2.config.Result;
import stringerx.apache.struts2.config.Results;
import stringerx.springframework.beans.factory.annotation.Autowired;
import stringerx.opensymphony.xwork2.Action;

import stringer.samples.simple.service.SimpleService;

@Results({
@Result(name=Action.SUCCESS, value = "/index.jsp")
,@Result(name=Action.ERROR, value = "/error.jsp")
})
public class SimpleAction {

The package names in the above code have to be converted into below:

package stringer.samples.simple.action;

import java.util.List;
import org.apache.struts2.config.Result;
import org.apache.struts2.config.Results;
import org.springframework.beans.factory.annotation.Autowired;
import com.opensymphony.xwork2.Action;



The Stringer provides “convertPackages” task for Ant to enable to convert the package names
in your build script.

<taskdef name="convertPackages"
classname="stringer.tool.ConvertPackagesTask"
classpath="stringer.jar"/>

<target name="convert">
<convertPackages encoding="UTF-8" verbose=”false”>
<fileset dir="src" includes="**/*.java"/>
<fileset dir="war" includes="**/web.xml, **/*.jsp"/>
</convertPackages>
</target>


8.2.2 web.xml
If you don’t convert package name using convertPackages ant task, change the
FilterDispatcher package name.

 stringerx.apache.struts2.dispatcher.FilterDispatcher
￿ org.apache.struts2.dispatcher.FilterDispatcher

 stringerx.springframework.web.context.ContextLoaderListener
￿ org.springframework.web.context.ContextLoaderListener


<filter>
Stringer Framework
Developer's Guide

32

<filter-name>Stringer</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<init-param>
<param-name>actionPackages</param-name>
<param-value>myapp.action</param-value>
</init-param>
</filter>


<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>


As you saw in the steps to run the sample, you also need to add entries for
SpringOpenEntityManagerInViewFilter. (This step is only required for using EntityManager.
HibernateTemplate doesn’t use this filter)

<filter>
<filter-name>Stringer</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<init-param>
<param-name>actionPackages</param-name>
<param-value>stringer.samples.transaction.action</param-value>
</init-param>
</filter>

<filter>
<filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
<filter-class>
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
</filter-class>
</filter>

<filter-mapping>
<filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
<filter-name>Stringer</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


8.2.3 taglib in JSPs
If you don’t convert JSPs using convertPackages ant task, change the URI in Stringer taglib
definition.

 uri="/stringer-tags" ￿ uri="/struts-tags"

<%@ taglib uri="/struts-tags" prefix="s" %>
Stringer Framework
Developer's Guide

33

<html>



8.2.4 applicationContext.xml
You need to change configurations in applicationContext.xml for Spring Framework. The new
xml for Spring looks like below:

Location: war/WEB-INF/applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

<context:annotation-config />
<context:component-scan base-package="stringer.samples.transaction" />

<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>/WEB-INF/hibernate.properties</value>
</list>
</property>
</bean>

<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${hibernate.connection.driver_class}" />
<property name="url" value="${hibernate.connection.url}" />
<property name="username" value="${hibernate.connection.username}" />
<property name="password" value="${hibernate.connection.password}" />
</bean>

<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL" />
<property name="showSql" value="${hibernate.show_sql}" />
Stringer Framework
Developer's Guide

34

</bean>
</property>
</bean>

<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />

</beans>

Basically, you can use the above configurations with only a change of base-package
depending on your project.

 base-package: Specify package path contains all action and service classes


8.2.5 persistence.xml
All configurations are done in applicationContext.xml in this sample, so you don’t have to
specify any information in persistence.xml. The following empty XML can be deployed in
META-INF under the root directory of the classpath.

Location: war/WEB-INF/classes/META-INF/persistence.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">

<persistence-unit name="sampleUnit" />

</persistence>


8.2.6 struts.xml
Struts2 injects table tags in form according to theme, but Stringer doesn’t support the theme
attribute. So, you need to change the default setting to use simple theme that doesn’t inject the
table tags if you want to generate with the same layout.

Location: war/WEB-INF/classes/struts.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>

<constant name="struts.ui.theme" value="simple" />

Stringer Framework
Developer's Guide

35


</struts>



8.3 HibernateTemplate
Most of the steps are same as the ones for EntityManager, but configurations in web.xml,
applicationContext.xml, etc. are different.
Let’s take a look at a sample application, “simple-real” to see the steps.

1. Go to <STRINGER-HOME>/samples/simple/
2. If you don’t’ create tables yet, run “ant createTables” task.
3. If you don’t’ make the “simple” build, run “ant compile” task.
4. Go to <STRINGER-HOME>/samples/simple_real/
5. Open build.properties file with your favorite text editor
6. Set “lib.real” property to <REAL-LIB> where you put required jar files.

## Libraries of Struts2, Spring and Hibernate
lib.real=/home/frameworks/lib

7. Run “ant convert” task from the command line.
(The converted files will be generated in src and war directories)
8. Run “ant deploy” task from the command line.
9. Start Tomcat and access the URL below:

http://localhost:8080/simple-real/

You will see same page as you saw on “simple” application, which is explained in Getting
Started” chapter, but it is running with Struts2, Spring and Hibernate jar files (without Stringer
jar)

Below are the explanations what to change for switching to real frameworks:

8.3.1 stringerx package name
The stringerx packages represent Struts2, Spring or Hibernate packages, so you need to
rename the package names to original name.

 stringerx.apache.struts2. ￿ org.apache.struts2.
 stringerx.springframework. ￿ org.springframework.
 stringerx.hibernate. ￿ org.hibernate.
 stringerx.opensymphony. ￿ com.opensymphony.

The Stringer provides “convertPackages” task for Ant to enable to convert the package names
in your build script.


8.3.2 web.xml
If you don’t convert package name using convertPackages ant task, change the
FilterDispatcher package name.

 stringerx.apache.struts2.dispatcher.FilterDispatcher
￿ org.apache.struts2.dispatcher.FilterDispatcher
Stringer Framework
Developer's Guide

36


 stringerx.springframework.web.context.ContextLoaderListener
￿ org.springframework.web.context.ContextLoaderListener


8.3.3 taglib in JSPs
If you don’t convert JSPs using convertPackages ant task, change the URI in Stringer taglib
definition.

 uri="/stringer-tags" ￿ uri="/struts-tags"


8.3.4 hibernate.properties
In this sample, you don’t have to change the settings. You just need to move the file to WEB-
INF directory.

Location: war/WEB-INF/hibernate.properties


8.3.5 applicationContext.xml
You need to add additional configurations in applicationContext.xml. The new xml for Spring
looks like below:

Location: war/WEB-INF/applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans …>

<context:annotation-config />
<context:component-scan base-package="stringer.samples.simple" />

<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>/WEB-INF/hibernate.properties</value>
</list>
</property>
</bean>

<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${hibernate.connection.driver_class}" />
<property name="url" value="${hibernate.connection.url}" />
<property name="username" value="${hibernate.connection.username}" />
<property name="password" value="${hibernate.connection.password}" />
</bean>

<bean id="sessionFactory" destroy-method="destroy"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configurationClass"
Stringer Framework
Developer's Guide

37

value="org.hibernate.cfg.AnnotationConfiguration"/>
<property name="annotatedClasses">
<list>
<value>stringer.samples.simple.persistence.Directory</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
</props>
</property>
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="transactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>

<bean id="hibernateTemplate"
class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="allowCreate" value="true" />
<property name="alwaysUseNewSession" value="false" />
</bean>

</beans>

You need to change the following lines at least:

 base-package: Specify package path contains all action and service classes
 propertyConfigure bean: Specify the location of hibernate.properties
 annotatedClasses: Specify persistence classes (Entity classes)


8.3.6 struts.xml
If you want to generate with the same layout as the Stringer in generated HTML, change the
default theme setting to simple.

Location: war/WEB-INF/classes/struts.xml

<constant name="struts.ui.theme" value="simple" />


Stringer Framework
Developer's Guide

38


9 Supported Functions
The Stringer partially supports Struts2, Spring Framework 2.5 and Hibernate 3 functions. This
chapter describes what are supported and what are not supported.

9.1 Struts2

Function
Stringer
Struts2
FilterDispatcher Yes Yes
Validation
No
Yes
Aware interface
Only ServletRequestAware
and ServletResponseAware
are available.
Yes
Struts Tags Partially supported, e.g. action,
a, form, textfield, select, radio,
checkbox, submit, etc.
For detail, please see
Reference document.
Yes
struts.xml Only package, action, result,
global-results and interceptor
tags are supported.
Yes
interceptor Yes (but parameters cannot be
set in Intercept)
Yes
struts.action.extension
No (always “.action”) Yes
Multiple packages in
actionPackages init-
param
Only one package can be
specified.
Yes
@Result Yes Yes
@Results Yes Yes

The rest of functions that is not described in the above table are not supported in Stringer.


9.2 Spring 2.5

Function
Stringer
Spring
applicationContext.xml base-package attribute in
component-scan and is, class,
scope (singleton or prototype)
attributes in bean tag are
available.
Yes
Scope
Only singleton and prototype
are supported
Yes
component-scan
base-package
Only scan the specified
package
Yes
(Scan all packages under
the specified location)
HibernateTemplate Only execute, executeFind, get,
loadAll, save, update, etc. are
supported. For detail, please
see Reference document.
Yes
Annotation


@Autowired Yes, but only available to Yes
Stringer Framework
Developer's Guide

39

specify in field and method (not
constructor)
@Qualifier Yes Yes
@Transactional Yes
(Only JDBC)
Yes
(Support JTA and JDBC)
Propagation REQUIRED, SUPPORTS,
MANDATORY,
REQUIRES_NEW,
NOT_SUPPORTED and
NEVER are available.
NESTED is not supported
Yes
Isolation Yes Yes
@PostConstruct Yes Yes
@PreDestroy
No
Yes

The rest of functions that is not described in the above table are not supported in Stringer.


9.3 Hibernate 3

Function
Stringer
Hibernate
1-1 relation Yes Yes
1-N relation
No Yes
N-N relation
No Yes
Supported Database Oracle 10g
MySQL
HSQLDB
Please see Hibernate
documents
hibernate.properties Yes Yes
hibernate.cfg.xml
No
Yes
Connection Pooling Yes if you use Oracle Driver.
(MySQL, HSQLDB are not
supported. Use JNDI
Datasource)
Yes
Data Source Yes Yes
Hibernate API


Session Only save, saveOrUpdate,
update, delete, get,
createCriteria, createSQLQuery
are supported.
Yes
Criteria Yes Yes
Query
No
Yes
SQLQuery list, uniqueResult,
executeUpdate and addEntity
are available.
The rest of APIs are not
supported.
Yes
Java Persistence API


EntityManager persist, find, remove, etc are
supported.
Yes
Query executeUpdate, getResultList
and getSingleResult are
supported.
Yes
Annotation


@Entity Yes (no use internally) Yes
Stringer Framework
Developer's Guide

40

@Table Only “name” can be specified.
catalog, schema,
uniqueConstraints are not
supported.
Yes
@Id Yes Yes
@GeneratedValue Yes Yes
GenerationType AUTO, IDENTITY, SEQUENCE
are available.
TABLE are not supported.
Yes
@SequenceGenerator name and sequenceName are
available.
allocationSize and initialValue
are not supported.
Yes
@Basic Yes (no use internally) Yes
@Column Only “name” is available.
The rest of elements are not
supported.
Yes
@Transient Yes Yes
@PersistenceContext Yes Yes

The rest of functions that is not described in the above table are not supported in Stringer.