You are on page 1of 61

Web Development

Using Spring MVC


Wenjie He
Gateway JUG, Nov. 4, 2008

Project Description
Mobile Member Portal
for Express Scripts, Inc. (ESI)

Main Requirements:
Built in ESI Framework -- Spring MVC/Castrol/XSL Capable of being viewed from the Blackberry (and iPhone) mobile web browser

ESI Member Portal (1)


Regular Web Version Login page

ESI Member Portal (2)


Regular Web Version Main page

ESI Member Portal (3)


Regular Web Version My Prescriptions Check Order Status

Demonstration of Mobile Version


Still under development Look and feel on iPhone

Background of Development Team


16 students in my Advanced Java class A few students in my Independent Study class At least half of the students only know core Java, but not Java EE. None of the students knows about the Spring Framework. The students are organized in four groups.

Development Phases
Develop using Servlets and JSP
Teaching Java EE basics Get experience in web development Two months

Develop using Spring and Hibernate


Learning + Developing in one months Only use Spring MVC basic features
8

Development Tools
Database: HSQLDB IDE: Eclipse Build tool: Ant Server: Tomcat Framework: Spring Persistence: Hibernate
9

User Interface Design


Login page and main page HTLM + CSS

10

Introduction to Spring Framework


Target on Enterprise JavaBeans (EJB)
Heavy weight vs. light weight Example: transaction support

Testing: Test-Driven Design (TDD)


Tight coupling vs. loose coupling

11

Why Spring in This Project?


ESI requirements Make web development more efficient
Streamline the procedure
Regular Servlets & JSP vs. Spring approach

Testability Easy maintenance

12

Spring Web MVC


One of the several modules in Spring Model-View-Controller (MVC) pattern
Separate user interface from application logic View user interface Model data and business services Controller interactions between model and view Easier to reuse code Easier to maintain web applications Other popular MVC frameworks: Struts, JSF 13

Front Controller Design Pattern


A front controller is a common web-application pattern
Entry point of the framework The first place a request meets the application A central servlet that dispatches requests to controllers The Spring web MVC is designed around
org.springframework.web.servlet.DispatcherServlet

It is integrated with the Spring IoC container. IoC Inverse of Control 14

15

Diagram of Request Processing Workflow

Library JAR Files


Database: server + driver
hsqldb.jar (691k)

Spring MVC: spring.jar, spring-webmvc.jar JSTL: jstl.jar, standard.jar Hibernate3: hibernate3.jar, and some more Hibernate tools:
hibernate-tools.jar, freemaker.jar

Servlets: servlet-api.jar
16

Setting Properties for Database


In build.properties
hsqldb.lib=/JavaEE/DBMS/hsqldb/lib db.name=esimobiledb hsqldb.dbfile=file:db/${db.name} hsqldb.dbalias=${db.name} db.driver=org.hsqldb.jdbcDriver db.url=jdbc:hsqldb:hsql://localhost/${db.name} db.user=sa db.pw= 17

Ant Target to Start DB Server


<path id="hsqldb.lib.path"> <fileset dir="${hsqldb.lib}"> <include name="hsqldb.jar" /> </fileset> </path> <target name="dbserver"> <java classname="org.hsqldb.Server fork="yes"> <classpath refid="hsqldb.lib.path"/> <arg value="-database.0"/> <arg value="${hsqldb.dbfile}"/> <arg value="-dbname.0"/> <arg value="${hsqldb.dbalias}"/> </java> </target>

18

Setting Properties for Tomcat


In build.properties
appserver.home=/JavaEE/Servers/Tomcat/apache-tomcat6.0.18 appserver.bin=${appserver.home}/bin appserver.lib=${appserver.home}/lib deploy.path=${appserver.home}/webapps tomcat.manager.url=http://localhost:8080/manager tomcat.manager.username=tomcat tomcat.manager.password=javaee

19

Ant Target to Start Tomcat


<target name="startTomcat"> <exec executable="cmd"> <arg value="/c"/> <arg value="${appserver.bin}/startup.bat"/> </exec> </target>

20

Configuration of Front Controller


In web.xml
<servlet> <servlet-name>esiMobile</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>esiMobile</servlet-name> <url-pattern>*.htm</url-pattern> </servlet-mapping>

21

Loading Spring Application Context


<servlet-name>: Developer chooses the servlet name for DispatcherServlet In this example, we use esiMobile

Default Spring application context file:


esiMobile-servlet.xml

When DispatcherServlet is loaded, the Spring application context in esiMobile-servlet.xml is loaded.


22

Choosing URL Pattern for Spring MVC


We can choose any URL pattern for
DispatcherServlet
<servlet-mapping> <servlet-name>esiMobile</servlet-name> <url-pattern>*.htm</url-pattern> </servlet-mapping>

Convention for most Spring MVC applications:


*.htm

They are virtual URLs. No such HTML files exist.


23

Object/Relational Mapping by Hibernate


Mapping Java objects to database tables Most useful in the Java-based middle-tier Encapsulate vendor-specific SQL code Reduces the effort needed to convert between relational database result-sets and graphs of Java objects

24

Start with a Table in Database


create table USER ( userid varchar(30) not null, username varchar(30), password varchar(30), firstname varchar(40), lastname varchar(40), email varchar(50), accountType varchar(20), lastlogintime date, primary key (userid) ); 25

Persistent Class for the Table


public class User { private String userid; private String username; private String password; private String firstname; private String lastname; private String email; private String accountType; private Date lastlogintime; public void setUserid(String userid) { this.userid = userid; }

26

Hibernate Mapping Files


User.hbm.xml
<hibernate-mapping> <class name="com.javux.esimobile.entity.User table="USER"> <id name="userid" type="string" unsaved-value="null" > <column name="userid" sql-type="varchar(30)" notnull="true"/> <generator class="assigned"/> </id> <property name="username" type="string" length="30"/>

27

Hibernate Configuration File


Hibernate.cfg.xml
<session-factory> <property name="connection.driver_class"> org.hsqldb.jdbcDriver</property> <property name="connection.url"> jdbc:hsqldb:hsql://localhost/esimobiledb</property> <property name="connection.username">sa</property> <property name="connection.password"></property> <property name="dialect"> org.hibernate.dialect.HSQLDialect</property> <mapping resource="com/javux/esimobile/entity/DrugOrder.hbm.xml"/>

28

Using Hibernate Tools to Generate Artifacts


Create Hibernate mapping files, e.g. User.hbm.xml Create Hibernate configuration file, hibernate.cfg.xml Run an Ant target to generate database schema Run an Ant target to generate persistent classes
29

Generate Database Schema


<taskdef name="htools" classname="org.hibernate.tool.ant.HibernateToolTask" classpathref="htools.lib" /> <target name="schemaGen"> <htools destdir="db"> <configuration configurationfile="${src.dir}/hibernate.cfg.xml" /> <hbm2ddl drop="true" outputfilename="ESImobileTables.sql" /> </htools> </target>

30

Generate Java Persistent Classes


<property name="src.dir" value="src" /> <target name="javaGen"> <htools destdir="${src.dir}"> <configuration configurationfile="${src.dir}/hibernate.cfg.xml" /> <hbm2java jdk5="true"/> </htools> </target> 31

Data Access Objects: Base Class


public class DAO { public static Session getSession() { Session session = (Session) DAO.session.get(); if (session == null) { session = sessionFactory.openSession(); DAO.session.set(session); } return session; } protected void begin() { getSession().beginTransaction(); }

32

Data Access Object for a Table


public class UserDAO extends DAO { public User getByUsername(String username) throws DatabaseException { try { begin(); Query q = getSession().createQuery( "from User where username = :username"); q.setString("username", username); User user = (User) q.uniqueResult(); commit(); return user; }

33

Bird View of Following Steps


Data binding Validation Authentication (services) Navigation

All built around controllers

34

Spring MVC Controllers


Central piece in Spring MVC pattern Responsible for dealing with browser requests Bridge between end user and applications services A controller is configured as another JavaBean in the Spring application context.
web web Dispatcher Servlet 35 Controller Service

Mapping URLs to Controllers


In esiMobile-servlet.xml
<bean id="simpleUrlMapping" class =

"org.springframework.web.servlet.handler.SimpleUrlHandler Mapping"> <property name ="mappings">


<props> <prop key ="/login.htm"> loginESImobileController</prop> <prop key ="/activate.htm"> activateController</prop> <prop key ="/activateA.htm"> activateAController</prop> <prop key ="/username.htm"> usernameController</prop>

36

Spring MVC Command Objects


A command object is a bean that holds the request parameters for easy access. A POJO (Plain Old Java Object) that has fields that can be accessed via setters and getters Data binding mapping form fields to the command class Store the data form fields properties of command Populate the fields of the form properties of command form fields 37

An Example of Command Class


public class LoginCommand { private String userId; private String password; public String getPassword() { return password; } public void setPassword(String password) { this.password = password; }

38

Presenting Model with a View


After processing, the controller sends the results back to browser.
Mapping view names to actual pages Displaying data in the model in the view pages

The view and model data is encapsulated in a ModelAndView object. Every controller execution method must return a ModelAndView object.
39

Declaring a View Resolver


The ModelAndView object contains a logical view name of the view page. A view resolver maps the logical view name to a real view page. In esiMobile-servlet.xml
<bean id="viewResolver" class =

"org.springframework.web.servlet.view.InternalResourceViewResolve r"> MainPage <property name="viewClass"><value>


org.springframework.web.servlet.view.JstlView </value></property> <property name ="prefix"><value> /WEB-INF/jsp/MainPage.jsp /WEB-INF/jsp/</value></property> <property name ="suffix"><value>.jsp</value></property> </bean>

40

Building a Controller:
LoginESImobileController (1)
package com.javux.esimobile.controllers; import import import import import import import import import com.javux.esimobile.commands.LoginCommand; com.javux.esimobile.dao.UserDAO; com.javux.esimobile.services.AuthenticationService; javax.servlet.http.HttpServletRequest; javax.servlet.http.HttpServletResponse; javax.servlet.http.HttpSession; org.springframework.validation.BindException; org.springframework.web.servlet.ModelAndView; org.springframework.web.servlet.mvc.SimpleFormController;

public class LoginESImobileController extends SimpleFormController { private AuthenticationService authenticationService; private UserDAO userDAO;

41

Building a Controller:
LoginESImobileController (2)
protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception{ HttpSession session = request.getSession( true ); LoginCommand loginCommand = (LoginCommand) command; String username = loginCommand.getUserId(); session.setAttribute("username",username); if ( authenticationService.authenticate(request, loginCommand, userDAO) ) { return new ModelAndView(getSuccessView()); } else { request.setAttribute("pass","fail"); return showForm(request, response, errors); } }

42

Building a Controller:
LoginESImobileController (3)

public void setAuthenticationService( AuthenticationService authenticationService) { this.authenticationService = authenticationService; } public void setUserDAO(UserDAO udao) { userDAO = udao; } 43

Dependency Injection (DI)


Making code simpler, easier to understand, and easier to test. Traditional way:
Objects responsible for obtaining its own references Lead to highly coupled and hard-to-test code

DI way:
Objects are given their dependencies at creation time by the container Loose coupling 44

Benefit of Loose Coupling


The depending object only knows about its dependencies by their interface
Not their implementation Not how they are instantiated

The dependency can be swapped out with a different implementation


ClassA
Injected into implementation1

InterfaceB
implementation2

45

Breaking up Application Context


Splitting the application context file into logical pieces can make maintenance easier. Putting the beans of services in
esiMobile-services.xml

Configuring the context loader


<context-param> <param-name> contextConfigLocation</param-name> <param-value> /WEB-INF/esiMobile-services.xml</param-value> </context-param>

Configuring Beans in esiMobile-services.xml


<beans> <bean id="userDAO" class="com.javux.esimobile.dao.UserDAO"> </bean>

UserDAO userDAO = new UserDAO();

<bean id="authenticationService" class="com.javux.esimobile.services.AuthenticationService"> </bean> <bean id="loginValidator" class="com.javux.esimobile.validators.LoginValidator"> </bean>

47

Configuring Controllers in Application Context (1)


In esiMobile-servlet.xml Configuring the command
<bean id="loginESImobileController" class="com.javux.esimobile.controllers.LoginESImo bileController"> <property name="sessionForm"><value>true</value></property> <property name="commandName"> <value>loginCommand</value></property> <property name="commandClass"> <value>com.javux.esimobile.commands.LoginComman d</value></property> 48

Configuring Controllers in Application Context (2)


Configuring bean properties
<property name="validator"> <ref bean="loginValidator" /> </property> <property name="authenticationService"> <ref bean="authenticationService" /> </property> <property name="userDAO"> <ref bean="userDAO" /> </property>

49

Configuring Controllers in Application Context (3)


Configuring views
<property name="formView"> <value>SignIn</value> </property> <property name="successView"> <value>MainPage</value> </property> </bean> 50

How DI Works
When creating bean loginESImobileController
Instantiating an instance of UserDAO UserDAO userDAO = new UserDAO(); Injecting userDAO into loginESImobileController loginESImobileController.setUserDAO(userDAO);

It is done by the container implicitly.


51

Validating Form Input


public class EmailLoginValidator implements Validator { public boolean supports(Class clazz) { return EmailLoginCommand.class.equals(clazz); } public void validate(Object obj, Errors errors) { ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", "error.email.empty"); EmailLoginCommand elc = (EmailLoginCommand) obj; if ( elc.getEmail().length() > 0) { if (elc.getEmail().indexOf("@") < 0) { errors.rejectValue("email", "error.email.invaid"); } } }

52

Rendering Externalized Mesages


Put all the messages in the file
resources/messages.properties

In esiMobile-servlet.xml
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessag eSource"> <property name="basename" value="resources/messages"/> </bean>

In JSP
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>

<spring:message code="esimobile.title"/> 53

Binding Form Data (1)


<%@ page session="true"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> <form:form method="post" commandName="loginCommand"> </form:form>

54

Binding Form Data (2)


<form:form method="post" commandName="loginCommand"> <td class='center' width='80'>Username: </td> <td class='left' width='120> <form:input path="userId"/> </td> <td class='center' width='80'>Password: </td> <td class='left' width='120'><form:password path="password"/></td> <form:errors path="userId" cssClass="errormsg"/> <form:errors path="password" cssClass="errormsg2"/> <input class='imgButton' type="image src="images/btnSignIn.gif" > </form:form>

55

Binding to a Drop Down Box (1)

Binding to a Drop Down Box (2)


<span id='selectInputKnow'> <form:select path='hearAboutId'> <form:option value='0' label='Select One'/> <form:option value='1' label='E-mail'/> <form:option value='2' label='Mail materials'/> <form:option value='3' label='Customer service phone line'/> <form:option value='4' label='Materials provided with your prescription'/> <form:option value='5' label='Pharmacist'/> <form:option value='6' label='Communication from your employer'/> <form:option value='7' label='Benefits ID card'/> <form:option value='8' label='Other'/> </form:select> </span>

Summarize
Dependency Injection Loose coupling Spring MVC configuration
Bean (service) configuration Controller configuration

Validation Data binding

Thank You!

You might also like