the spring framework, - software summitsoftwaresummit.com/2005/speakers/raiblespringoverview.pdf ·...
TRANSCRIPT
The Spring Framework,Simplifying J2EE
Matt Raiblewww.springlive.com
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 1
Introductions
Your experience with Spring?Your experience with J2EE?What do you hope to learn in this session?Open Source experience: Ant, XDoclet, Hibernate?Favorite IDE? Favorite OS?
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 2
Matt
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 3
Raible
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 4
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 5
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 6
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 7
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 8
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 9
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 10
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 11
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 12
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 13
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 14
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 15
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 16
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 17
Who is Matt Raible?Father, Husband, Open Source Practice Leader
Developing websites since 1994 - Developing J2EE webapps since 1999
Committer on several open source projects: AppFuse, Roller Weblogger, XDoclet, Struts Menu, Display Tag
J2EE 5.0 and JSF 1.2 Expert Group Member
Author: Spring Live (SourceBeat) and contributor to Pro JSP (Apress)
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 18
J2EE 5.0 and JSF 1.2 Expert Group Member
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 19
Spring Mission Statement
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 20
What is Spring?
A J2EE Framework designed to make building applications easierProvides a means to manage your business objects and their dependenciesInversion of Control allows classes to be loosely coupled and dependencies written in XMLÀ la carte framework that allows you to pick and choose features to use
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 21
Spring Modules
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 22
Sample Architecture
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 23
The BeanFactory
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 24
XML Context File<?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="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties"/>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
</beans>
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost/equinox
jdbc.username=root
jdbc.password=
jdbc.properties:
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 25
ClassPathXmlApplicationContext - load files from classpathFileSystemXmlApplicationContext - load from filesystem (relative or absolute paths)StaticXmlApplicationContext - allows programmatic registration of beansXmlWebApplicationContext - used by ContextLoaderListener to read paths from web.xml
Get that Context!
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 26
ClassPathXmlApplicationContext
ApplicationContext ctx = new ClassPathXmlApplicationContext("/WEB-INF/applicationContext.xml");
String paths[] = new String[] {"/WEB-INF/applicationContext-hibernate.xml",
"/WEB-INF/applicationContext.xml"};
ApplicationContext ctx = new ClassPathXmlApplicationContext(paths);
ApplicationContext ctx = new ClassPathXmlApplicationContext("/WEB-INF/applicationContext*.xml");
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 27
Dependency Injection
Hollywood Principle:“Don’t call me, I’ll call you.”
http://martinfowler.com/articles/injection.html
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 28
Dependency Injection
Lookup dependencies vs. Exposing dependencies
Easy to mock dependencies (i.e. in unit tests)
Spring supports constructor injection, setter injection and method injection
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 29
Example: Controller and DAOController has a setter or a constructor argument for the DAO
DAO is configured as a dependency of the Controller
Makes it easy to swap out implementations
Tests can verify operations succeed on the interface
<bean id="userController" class="org.appfuse.web.UserController"> <property name="userDAO" ref="userDAO"/> </bean> <bean id="userDAO" class="org.appfuse.dao.UserDAOHibernate"> <property name="sessionFactory" ref="sessionFactory"/> </bean>
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 30
Code before IoC
public class UserController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { Connection conn = DatabaseUtils.getConnection(); UserDAO dao = DAOFactory.createUserDAO("hibernate", conn); List users = dao.getUsers();
DatabaseUtils.closeConnection(conn); return new ModelAndView("userList", "users", users); }}
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 31
Code after IoC
public class UserController implements Controller { private UserDAO dao = null;
public void setUserDAO(UserDAO userDAO) { this.dao = userDAO; }
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { List users = dao.getUsers(); return new ModelAndView("userList", "users", users); }}
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 32
Setter Injection
public class UserController implements Controller { private UserDAO dao = null;
public void setUserDAO(UserDAO userDAO) { this.dao = userDAO; }
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { List users = dao.getUsers(); return new ModelAndView("userList", "users", users); }}
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 33
Setter Injection
public class UserController implements Controller { private UserDAO dao = null;
public void setUserDAO(UserDAO userDAO) { this.dao = userDAO; }
<bean id="userController" class="org.appfuse.web.UserController"> <property name="userDAO" ref="userDAO"/></bean>
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 34
Constructor Injection
public class UserController implements Controller { private UserDAO dao = null;
public UserController(UserDAO userDAO) { this.dao = userDAO; }
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { List users = dao.getUsers(); return new ModelAndView("userList", "users", users); }}
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 35
Constructor Injection
public class UserController implements Controller { private UserDAO dao = null;
public UserController(UserDAO userDAO) { this.dao = userDAO; }
<bean id="userController" class="org.appfuse.web.UserController"> <constructor-arg index=”0” ref="userDAO"/></bean>
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 36
Spring vs. J2EE
It’s not really a comparison, Spring builds off J2EE and merely makes the APIs easierIt’s still using many of J2EE’s and Java’s underlying infrastructureEJB vs. Spring Managed POJOsClustering and Fail-over supported better by EJB
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 37
Spring simplifies EJBsAbstract classes in org.springframework.ejb.support override methods that you normally don’t implement
Expose EJBs as Spring beans with classes in org.springframework.ejb.access package
Configuring a JtaTransactionManager will allow Spring beans to participate in CMT
<bean id="simpleService" lazy-init="true"
class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean">
<property name="jndiName" value="jndiName"/>
<property name="cacheHome" value="true"/>
<property name="businessInterface" value="org.appfuse.ejb.SimpleService"/>
</bean>
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 38
Testing Spring ApplicationsEasy to mock dependencies with EasyMock and jMock
Load context in tests and bind dependencies as you would in productionTIP: Use a static block or Spring classes in Spring Mock (org.springframework.test package)
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 39
Spring MocksStubs for Servlet and JNDI API
Spring’s org.springframework.test package has a number of base classes to simplify testingAbstractDependencyInjectionSpringContextTests - can do both setter or field-based dependency injection, cached context files
AbstractTransactionalDataSourceSpringContextTests - allows you to easily clear data from tables and rolls back any data entered into the database
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 40
AbstractTransactionalDataSourceSpringContextTests
public class UserManagerIntegrationTest extends AbstractTransactionalDataSourceSpringContextTests {
private UserManager userManager;
public void setUserManager(UserManager userManager) {
this.userManager = userManager;
}
protected String[] getConfigLocations() {
return new String[] {"classpath*:/WEB-INF/applicationContext*.xml"};
}
protected void onSetUpInTransaction() throws Exception {
deleteFromTables(new String[] {"app_user"});
}
public void testGetUsers() {
User kid1 = new User();
kid1.setFirstName("Abbie");
kid1.setLastName("Raible");
User kid2 = new User();
kid2.setFirstName("Jack");
kid2.setLastName("Raible");
userManager.saveUser(kid1);
userManager.saveUser(kid2);
assertEquals(2, userManager.getUsers().size());
}
}
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 41
Data Access Support
Meaningful ExceptionsNo more try/catch/finallyDaoSupport and Template classes for many frameworks
Hibernate, iBATIS, JDO, OJB and TopLink
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 42
Rich Exception Hierarchy
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 43
Data Access Examples
UserDAOTestHibernateiBATISSpring JDBCOJBJDO
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 44
Hibernatepublic class UserDAOHibernate extends HibernateDaoSupport implements UserDAO {
public List getUsers() { return getHibernateTemplate().find("from User"); }
public User getUser(Long id) { User user = (User) getHibernateTemplate().get(User.class, id); if (user == null) { throw new ObjectRetrievalFailureException(User.class, id); } return user; }
public void saveUser(User user) { getHibernateTemplate().saveOrUpdate(user); }
public void removeUser(Long id) { getHibernateTemplate().delete(getUser(id)); }}
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 45
iBATISpublic class UserDAOiBatis extends SqlMapClientDaoSupport implements UserDAO {
public List getUsers() { return getSqlMapClientTemplate().queryForList("getUsers", null); }
public User getUser(Long id) { User user = (User) getSqlMapClientTemplate().queryForObject("getUser", id);
if (user == null) { throw new ObjectRetrievalFailureException(User.class, id); }
return user; }
public void removeUser(Long id) { getSqlMapClientTemplate().update("deleteUser", id); }}
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 46
iBATIS SQL<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd">
<sqlMap namespace="UserSQL"> <select id="getUser" parameterClass="java.lang.Long" resultClass="org.appfuse.model.User"> select id, first_name as firstName, last_name as lastName from app_user where id=#id#; </select> <select id="getUsers" resultClass="org.appfuse.model.User"> select id, first_name as firstName, last_name as lastName from app_user; </select> <delete id="deleteUser" parameterClass="java.lang.Long"> delete from app_user where id = #id#; </delete>
</sqlMap>
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 47
JDOpublic class UserDAOJdo extends JdoDaoSupport implements UserDAO { public List getUsers() { Collection users = getJdoTemplate().find(User.class); users = getPersistenceManager().detachCopyAll(users); return new ArrayList(users); }
public User getUser(Long id) { User user = (User) getJdoTemplate().getObjectById(User.class, id); if (user == null) { throw new ObjectRetrievalFailureException(User.class, id); } return (User) getPersistenceManager().detachCopy(user); }
public void saveUser(User user) { if (user.getId() == null) { getJdoTemplate().makePersistent(user); } else { getPersistenceManager().attachCopy(user, true); } }
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 48
OJBpublic class UserDAOOjb extends PersistenceBrokerDaoSupport implements UserDAO { public List getUsers() { return new ArrayList(getPersistenceBrokerTemplate(). getCollectionByQuery(new QueryByCriteria(User.class))); }
public User getUser(Long id) { Criteria criteria = new Criteria(); criteria.addEqualTo("id", id); User user = (User) getPersistenceBrokerTemplate() .getObjectByQuery(new QueryByCriteria(User.class, criteria)); if (user == null) { throw new ObjectRetrievalFailureException(User.class, id); }
return user; }
public void saveUser(User user) { getPersistenceBrokerTemplate().store(user); }
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 49
Spring JDBC
public class UserDAOJdbc extends JdbcDaoSupport implements UserDAO { public List getUsers() { return new UsersQuery(getDataSource()).execute(); } public User getUser(Long id) { List users = new UserQuery(getDataSource()).execute(new Object[]{id}); if (users.isEmpty()) { throw new ObjectRetrievalFailureException(User.class, id); } return (User) users.get(0); } public void removeUser(Long id) { getJdbcTemplate().update("DELETE FROM app_user WHERE id = ?", new Object[] {id}); }
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 50
Spring JDBC
public class UserDAOJdbc extends JdbcDaoSupport implements UserDAO { public List getUsers() { return new UsersQuery(getDataSource()).execute(); } public User getUser(Long id) { List users = new UserQuery(getDataSource()).execute(new Object[]{id}); if (users.isEmpty()) { throw new ObjectRetrievalFailureException(User.class, id); } return (User) users.get(0); } public void removeUser(Long id) { getJdbcTemplate().update("DELETE FROM app_user WHERE id = ?", new Object[] {id}); }
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 51
MappingSqlQuery // Query to get a single User
class UserQuery extends MappingSqlQuery {
public UserQuery(DataSource ds) {
super(ds, "SELECT * FROM app_user WHERE id = ?");
super.declareParameter(new SqlParameter("id", Types.INTEGER));
compile();
}
protected Object mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(new Long(rs.getLong("id")));
user.setFirstName(rs.getString("first_name"));
user.setLastName(rs.getString("last_name"));
return user;
}
}
// Query to get a list of User objects
class UsersQuery extends MappingSqlQuery {
public UsersQuery(DataSource ds) {
super(ds, "SELECT * FROM app_user");
compile();
}
protected Object mapRow(ResultSet rs, int rowNum) throws SQLException {
...
}
}
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 52
Spring MVC
Front-Controller Servlet: DispatcherServlet
Controllers loaded as beans from servlet’s XML context files
ContextLoaderListener loads other XML context files
Many different Controller options: Controller, SimpleFormController, Wizard
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 53
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 54
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 55
Pros:Lifecyle for overriding binding, validation, etc.Integrates with many view options seamlessly: JSP/JSTL, Tiles, Velocity, FreeMarker, Excel, XSL, PDFInversion of Control makes it easy to test
Cons:Configuration intensive - lots of XMLRequires writing lots of code in JSPsAlmost too flexible - no common parent Controller
Controller and JSP Examples
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 56
Spring Controllerpublic class UserController implements Controller {
private final Log log = LogFactory.getLog(UserController.class); private UserManager mgr = null;
public void setUserManager(UserManager userManager) {
this.mgr = userManager; }
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
if (log.isDebugEnabled()) { log.debug("entering 'handleRequest' method...");
}
return new ModelAndView("userList", "users", mgr.getUsers()); }
}
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 57
Spring Controllerpublic class UserController implements Controller {
private final Log log = LogFactory.getLog(UserController.class); private UserManager mgr = null;
public void setUserManager(UserManager userManager) {
this.mgr = userManager; }
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
if (log.isDebugEnabled()) { log.debug("entering 'handleRequest' method...");
}
return new ModelAndView("userList", "users", mgr.getUsers()); }
}
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 58
Display Tag<display:table name="users" class="list" requestURI="" id="userList" export="true">
<display:column property="id" sort="true" href="editUser.html" paramId="id" paramProperty="id" titleKey="user.id"/>
<display:column property="firstName" sort="true" titleKey="user.firstName"/> <display:column property="lastName" sort="true" titleKey="user.lastName"/>
<display:column titleKey="user.birthday" sort="true" sortProperty="birthday"> <fmt:formatDate value="${userList.birthday}" pattern="${datePattern}"/>
</display:column></display:table>
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 59
Spring: userForm.jsp
<form method="post" action="<c:url value="/editUser.html"/>"
onsubmit="return validateUser(this)" name="userForm"><spring:bind path="user.id">
<input type="hidden" name="id" value="${status.value}"/> </spring:bind>
<table class="detail"><tr>
<th><label for="firstName"> <fmt:message key="user.firstName"/>:</label></th>
<td> <spring:bind path="user.firstName">
<input type="text" name="${status.expression}" id="firstName" value="${status.value}"/>
<span class="fieldError">${status.errorMessage}</span> </spring:bind>
</td></tr>
<tr>
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 60
Spring: userForm.jsp
<form method="post" action="<c:url value="/editUser.html"/>"
onsubmit="return validateUser(this)" name="userForm"><spring:bind path="user.id">
<input type="hidden" name="id" value="${status.value}"/> </spring:bind>
<table class="detail"><tr>
<th><label for="firstName"> <fmt:message key="user.firstName"/>:</label></th>
<td> <spring:bind path="user.firstName">
<input type="text" name="${status.expression}" id="firstName" value="${status.value}"/>
<span class="fieldError">${status.errorMessage}</span> </spring:bind>
</td></tr>
<tr>
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 61
Spring Supports many Java MVC Frameworks
ContextLoaderListener loads beans into ServletContext - can retrieve with:WebApplicationContext ctx =
WebApplicationContextUtils.getWebApplicationContext(servletContext);
Struts has ContextLoaderPlugin and ActionSupport classesWebWork has SpringObjectFactory
Tapestry - override BaseEngine and stuff the context into the Global
JSF - DelegatingVariableResolver
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 62
Spring Web Flow<webflow id="userFlow" start-state="setupForm">
<action-state id="setupForm">
<action bean="userFormAction"/>
<transition on="success" to="display.nameForm"/>
</action-state>
<view-state id="display.nameForm" view="flow/name">
<transition on="submit" to="display.addressForm">
<action bean="userFormAction" method="bindAndValidate"/>
</transition>
<transition on="cancel" to="finish"/>
</view-state>
<view-state id="display.addressForm" view="flow/address">
<transition on="previous" to="display.nameForm">
<action bean="userFormAction" method="bindAndValidate"/>
</transition>
<transition on="submit" to="display.otherForm">
<action bean="userFormAction" method="bindAndValidate"/>
</transition>
<transition on="cancel" to="finish"/>
</view-state>
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 63
MVC Tips
Using IoC for setting Controller/Action dependencies makes it easy to mock themJSP 2.0 Tag files in JIRA - for syntax simplificationUse SiteMesh - simple yet powerfulAppFuse and Equinox have good integration examples
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 64
Transactions
Much easier to use than UserTransaction in J2EECMT-like capabilities with XML and transparent AOPSupports Commons Attributes and JDK 5 AnnotationsPluggable Transaction Managers, including JTA
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 65
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 66
Spring Example
public void saveUser(final User user) {
txTemplate.execute(new TransactionCallbackWithoutResult() { public void doInTransactionWithoutResult(TransactionStatus status) {
dao.saveUser(user); }
});}
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 67
Declarative Transactions<?xml version="1.0" encoding="UTF-8"?>
<?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="txProxyTemplate" abstract="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<bean id="userManager" parent="txProxyTemplate">
<property name="target">
<bean class="org.appfuse.service.impl.UserManagerImpl">
<property name="userDAO" ref="userDAO"/>
</bean>
</property>
</bean>
</beans>
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 68
Spring AOP
What is AOP? “Aspect-Oriented Programming”
Handling the 20% of problems that Object-Oriented programming can’t solve
A way of removing code duplication between classes that aren’t in the same hierarchy
Applications have core concerns (functionality) and cross cutting concerns (aspects)
With Spring AOP, an interceptor is used to inspect method calls
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 69
Logging ExampleReplace log.debug(”...”) at beginning and end of method calls
In order to intercept a bean’s method, it must be configured as a proxied class
org.springframework.aop.interceptor.SimpleTraceInterceptor
Practical AOP Examples:
Transactions
Caching in your middle-tier
Performance Monitoring
Event Notification
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 70
SimpleTraceInterceptorAdd a “preInterceptors” property
Change log4j.xml to show log messages
<bean id="userManager" parent="txProxyTemplate">
<property name="target">
<bean class="org.appfuse.service.impl.UserManagerImpl">
<property name="userDAO" ref="userDAO"/>
</bean>
</property>
<property name="preInterceptors">
<list>
<ref bean="loggingInterceptor"/>
</list>
</property>
</bean>
<logger name="org.springframework.aop.interceptor">
<level value="DEBUG"/>
</logger>
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 71
Related Projects
Acegi Security for SpringSpring Rich Client ProjectSpring Web FlowSpring Web Services FrameworkTrailsAppFuse and Equinox
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 72
Remoting & Web ServicesRMI using RmiProxyFactoryBean and RmiServiceExporter
Spring’s HTTP Invoker: Java serialization over HTTP using HttpInvokerProxyFactoryBean and HttpInvokerServiceExporter
Hessian: lightweight binary HTTP-based protocol
Burlap: XML-based alternative to Hessian
JAX RPC: for Web Services
http://www.springframework.org/docs/reference/remoting.html
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 73
ToolsSpring IDE Plugin For Eclipse
http://springide.org
BeanDochttp://opensource.atlassian.com/confluence/spring/display/BDOC/Home
Gaijin Studiohttp://gaijin-studio.sf.net
Screenshots
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 74
Resources
Web: www.springframework.org and forum.springframework.orgPrint: Spring Live, Pro Spring, Spring in Action and Professional Spring DevelopmentExamples: AppFuse (appfuse.dev.java.net), Equinox (equinox.dev.java.net), JPetstoreTraining: Virtuas, Interface21
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 75
Please fill out the evals!
http://tinyurl.com/agczp
Colorado Software Summit: October 23 – 28, 2005 © Copyright 2005, Virtuas, LLC
Matt Raible — The Spring Framework, Simplifying J2EE Page 76