By Bruce A. Tate, Justin Gehtland
Book Price: $29.95 USD
£20.95 GBP
PDF Price: $23.99
Cover | Table of Contents | Colophon
com.springbook, unless otherwise specified.)public class Bike {
private String manufacturer;
private String model;
private int frame;
private String serialNo;
private double weight;
private String status;
public Bike(String manufacturer, String model, int frame,
String serialNo, double weight, String status) {
this.manufacturer = manufacturer;
this.model = model;
this.frame = frame;
this.serialNo = serialNo;
this.weight = weight;
this.status = status;
}
public String toString( ) {
return "Bike : " +
"manufacturer -- " + manufacturer +
"\n: model -- " + model +
"\n: frame -- " + frame +
"\n: serialNo -- " + serialNo +
"\n: weight -- " + weight +
"\n: status -- " + status +
".\n";
}
public String getManufacturer( ) { return manufacturer; }
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
public String getModel( ) { return model; }
public void setModel(String model) { this.model = model; }
public int getFrame( ) { return frame; }
public void setFrame(int frame) { this.frame = frame; }
public String getSerialNo( ) { return serialNo; }
public void setSerialNo(String serialNo) { this.serialNo = serialNo; }
public double getWeight( ) { return weight; }
public void setWeight(double weight) { this.weight = weight; }
public String getStatus( ) { return status; }
public void setStatus(String status) { this.status = status; }
}aService (which is a reference to an instance of
Service) to satisfy the dependency.
http://springframework.org/ ). To run all of
the examples for this book, you'll want to get
Spring version 1.1, or later. Follow all of the directions for your
platform.RentABikeAssembler object with Spring.http://www.springframework.org. That will
point you to sourceforge, where you'll get the best
version for your platform. We used Version 1.1. You will need to add
a new folder to your project, war\WEB-INF\lib,
and put the Spring libraries there (everything in the
\dist folder of your Spring distribution).<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="rentaBike" class="ArrayListRentABike">
<property name="storeName"><value>"Bruce's Bikes"</value></property>
</bean>
<bean id="commandLineView" class="CommandLineView">
<property name="rentaBike"><ref bean="rentaBike"/></property>
</bean>
</beans>public class RentABikeTest extends TestCase{
private RentABike rentaBike;
public void setUp( ) {
rentaBike = new ArrayListRentABike("Bruce's Bikes");
}
public void testGetName( ) {
assertEquals("Bruce's Bikes", rentaBike.getStoreName( ));
}
public void testGetBike( ) {
Bike bike = rentaBike.getBike("11111");
assertNotNull(bike);
assertEquals("Shimano", bike.getManufacturer( ));
}
public void testGetBikes( ) {
List bikes = rentaBike.getBikes( );
assertNotNull(bikes);
assertEquals(3, bikes.size( ));
}
}http://jakarta.apache.org/tomcat. There,
you'll find Apache Tomcat 5.0.27, which is the
version that we're using for all of our examples. If
you want to use something else, that's okay.
You'll just need some type of servlet container that
supports:RentABike, so that you can do simple
create/read/update/delete (CRUD) methods. Example 2-1 gives the new façade.public interface RentABike {
List getBikes( );
Bike getBike(String serialNo);
void saveBike(Bike bike);
void deleteBike(Bike bike);
void setStoreName(String name);
String getStoreName( );
}
RentABike for the business logic,
you'll use Spring to help you organize and configure
the application, and you'll deploy it on Tomcat.
http://java.sun.com/products/jsp/jstl/, or
packaged with Spring). Add standard.jar,
jstl.jar, c.tld and
fmt.tld to your
war\WEB-INF\lib folder. You'll
link them through an rentaBikeApp-Servlet.xml by
adding the following element (Example 2-13).BikesController (Example 2-20).public class ControllerTest extends TestCase {
private ApplicationContext ctx;
public void setUp( ) throws Exception {
ctx = new FileSystemXmlApplicationContext(
"war/WEB-INF/rentaBikeApp-servlet.xml");
}
public void testBikesController( ) throws Exception {
BikesController controller = (BikesController)
ctx.getBean("bikesController");
ModelAndView mav = controller.handleRequest(null, null);
RentABike store = (RentABike) mav.getModel( ).get("rentaBike");
assertNotNull(store);
assertTrue(store.getBikes( ).size( ) == 3);
}
}
FileSystemXmlApplicationContext class to load the
context configuration explicitly.public void testBikeValidator( ) throws Exception {
BikeValidator v = (BikeValidator) ctx.getBean("bikeValidator");
Bike bike = new Bike("test", "test", 1, "test", 2.00, "test");
Errors errs = new BindException(bike, "bike");
v.validate(bike, errs);
assertFalse(errs.hasErrors( ));
bike = new Bike( );
errs = new BindException(bike, "bike");
v.validate(bike, errs);
assertTrue(errs.hasErrors( ));
}web.xml configures your central dispatcher and
struts-config.xml manages the Struts Controller.
Example 3-1 shows web.xml.<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
<web-app>
<display-name>RentABike</display-name>
<description>
Renting bikes for fun and profit.
</description>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/rentABikeApp-servlet.xml
</param-value>
</context-param>
<servlet>
<servlet-name>SpringContext</servlet-name>
<servlet-class>
org.springframework.web.context.ContextLoaderServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>RentABike</servlet-name>
<servlet-class>
org.apache.struts.action.ActionServlet
</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>validate</param-name>
<param-value>true</param-value>12
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>RentABike</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>
start.html
</welcome-file>
</welcome-file-list>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.properties</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.util.Log4jConfigListener
</listener-class>
</listener>
<taglib>
<taglib-uri>/spring</taglib-uri>
<taglib-location>/WEB-INF/spring.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>http://java.sun.com/jstl/core</taglib-uri>
<taglib-location>/WEB-INF/c.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/struts</taglib-uri>
<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
</taglib>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
</web-app>web.xml configures your central dispatcher and
struts-config.xml manages the Struts Controller.
Example 3-1 shows web.xml.<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
<web-app>
<display-name>RentABike</display-name>
<description>
Renting bikes for fun and profit.
</description>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/rentABikeApp-servlet.xml
</param-value>
</context-param>
<servlet>
<servlet-name>SpringContext</servlet-name>
<servlet-class>
org.springframework.web.context.ContextLoaderServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>RentABike</servlet-name>
<servlet-class>
org.apache.struts.action.ActionServlet
</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>validate</param-name>
<param-value>true</param-value>12
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>RentABike</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>
start.html
</welcome-file>
</welcome-file-list>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.properties</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.util.Log4jConfigListener
</listener-class>
</listener>
<taglib>
<taglib-uri>/spring</taglib-uri>
<taglib-location>/WEB-INF/spring.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>http://java.sun.com/jstl/core</taglib-uri>
<taglib-location>/WEB-INF/c.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/struts</taglib-uri>
<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
</taglib>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
</web-app>
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
<html>
<f:view>
<head>
<title>
<h:outputText value="#{rentABike.storeName}"/>
</title>
</head>
<body>
<h1><h:outputText value="#{rentABike.storeName}"/></h1>
<h:outputText value="Edit a bike"/>
<h:form>
<h:dataTable value="#{rentABike.bikes}" var="bike">
<h:column>
<h:commandLink action="#{editBikeController.editBike}">
<h:outputText
value="#{bike.manufacturer} - #{bike.model}"/>
<f:param name="bikeSerialNo" value="#{bike.serialNo}"/>
</h:commandLink>
</h:column>
</h:dataTable>
<h:outputText value="<br/><br/>" escape="false"/>
<h:commandLink action="#{editBikeController.newBike}">
<h:outputText value="Add a new bike"/>
</h:commandLink>
</h:form>
</body>
</f:view>
</html>/bike.jsp, you did this: ...
<h:form>
<h:dataTable value="#{rentABike.bikes}" var="bike">
<h:column>
...
</h:column>
</h:dataTable>
...
</h:form>
...
#{rentABike.bikes} value binding references
the bikes property of the bean named rentABike.
Recall that previously, the rentABike bean was
defined in a Spring configuration file, like this:<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dt\
d/spring-beans.dtd">
<beans>
<bean name="rentABike" class="com.springbook.ArrayListRentABike">
<property name="storeName"><value>Bruce's Bikes</value></property>
</bean>
...
</beans>
DelegatingVariableResolver
from the org.springframework.web.jsf package. You
declare that variable resolver, which extends the JSF expression
language to include references to Spring beans, in the faces
configuration file:<faces-config>
<application>
<variable-resolver>
org.springframework.web.jsf.DelegatingVariableResolver
</variable-resolver>
</application>
...
</faces-config>
http://mysql.org. Download it and follow the
installation directions. Make sure to pay special attention to the
instructions for initializing and modifying the user accounts for the
installation; the instructions can vary greatly from one version to
the next.mysql> create database bikestore; Query OK, 1 row affected (0.00 sec) mysql> show databases; +------------+ | Database | +------------+ | bikestore | | mysql | | test | +------------+ 3 rows in set (0.00 sec)
http://mysql.org. Download it and follow the
installation directions. Make sure to pay special attention to the
instructions for initializing and modifying the user accounts for the
installation; the instructions can vary greatly from one version to
the next.mysql> create database bikestore; Query OK, 1 row affected (0.00 sec) mysql> show databases; +------------+ | Database | +------------+ | bikestore | | mysql | | test | +------------+ 3 rows in set (0.00 sec)
public List getBikes( ) {
final ArrayList results = new ArrayList( );
JdbcTemplate template = new JdbcTemplate( );
class BikesHandler implements RowCallbackHandler {
public void processRow(ResultSet rs) throws SQLException {
Bike bike = new Bike(rs.getString(MANUFACTURER),
rs.getString(MODEL), rs.getInt(FRAME), rs.getString(SERIALNO),
rs.getDouble(WEIGHT), rs.getString(STATUS));
results.add(bike);
}
}
template.query("SELECT * FROM bikes", new BikesHandler( ));
return results;
}
public Bike getBike(String serialNo) {
final Bike bike = new Bike( );
JdbcTemplate template = new JdbcTemplate( );
class BikeHandler implements RowCallbackHandler {
public void processRow(ResultSet rs) throws SQLException {
bike.setManufacturer(rs.getString(MANUFACTURER));
bike.setModel(rs.getString(MODEL));
bike.setFrame(rs.getInt(FRAME));
bike.setSerialNo(rs.getString(SERIALNO));
bike.setWeight(rs.getDouble(WEIGHT));
bike.setStatus(rs.getString(STATUS));
}
}
template.query("SELECT * FROM bikes WHERE bikes.serialNo = '"
+ serialNo + "'", new BikeHandler( ));
return bike;
}MappingSqlQuery class
for
each kind of reservation search. Specify parameters for each of the
parameters of the query, and then set the types for each of the
parameters. As before, you'll specify a method to
map each row, with an inner class. Example 4-9 shows
the code we have so far.abstract class FindReservations extends MappingSqlQuery {
protected List reservations = new ArrayList( );
protected FindReservations(DataSource dataSource, String query) {
super(dataSource, query);
}
protected Object mapRow(ResultSet rs, int rownum)
throws SQLException {
int resId = rs.getInt(1);
int bikeId = rs.getInt(2);
int custId = rs.getInt(3);
Date resDate = rs.getDate(4);
Bike bike = getBike(bikeId);
Customer customer = getCustomer(custId);
Reservation reservation = new Reservation(resId, bike,
customer, resDate);
reservations.add(reservation);
return reservation;
}
abstract List findReservations(int param);
}
class FindReservationsByCustomer extends FindReservations {
public FindReservationsByCustomer(DataSource dataSource) {
super(dataSource,
"SELECT * FROM reservations WHERE custId = ?");
declareParameter(new SqlParameter(Types.INTEGER));
compile( );
}
public List findReservations(int param) {
execute(param);
return this.reservations;
}
}
class FindReservationsByBike extends FindReservations {
public FindReservationsByBike(DataSource dataSource) {
super(dataSource,
"SELECT * FROM reservations WHERE bikeId = ?");
declareParameter(new SqlParameter(Types.INTEGER));
compile( );
}
public List findReservations(int param) {
execute(param);
return reservations;
}
}http://www.easymock.org and place the
easymock.jar file in your
project's classpath. We've added it
to our /lib folder.public void testGetBikesWithMocks( ) throws Exception {
DataSource mockDataSource;
Connection mockConnection;
Statement mockStatement;
ResultSet mockRS;
MockControl controlDataSource =
MockControl.createControl(DataSource.class);
MockControl controlConnection =
MockControl.createNiceControl(Connection.class);
MockControl controlStatement =
MockControl.createControl(Statement.class);
MockControl controlRS =
MockControl.createControl(ResultSet.class);
mockDataSource = (DataSource)controlDataSource.getMock( );
mockConnection = (Connection)controlConnection.getMock( );
mockStatement = (Statement)controlStatement.getMock( );
mockRS = (ResultSet)controlRS.getMock( );http://www.neward.net.