spring - users.csc.calpoly.eduusers.csc.calpoly.edu/~djanzen/courses/509s09/spring.pdf ·...

46
Copyright ©2009 David S. Janzen Spring Tutorial David Janzen 4/24/09

Upload: others

Post on 30-Sep-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

  • Copyright ©2009 David S. Janzen

    Spring Tutorial

    David Janzen

    4/24/09

  • Copyright ©2009 David S. Janzen

    Spring Motivation• Problems:

    • Web and GUI applications are traditionally hard to test

    • Screen-scraping is difficult

    • Decoupling testable code from view and flow code

    is difficult

    • Web applications contain a lot of “plumbing” or

    “glue” code

    • Servlet controllers

    • Configuration

    • JNDI lookups

    • Persistence mechanisms

  • Copyright ©2009 David S. Janzen

    Spring Background

    • Opportunities:

    • We’ve learned a lot about improving design in the

    last ten years

    • UML

    • Design Patterns

    • Frameworks

    • Plethora of good code available for reuse

    • Open-Source projects

    • COTS

  • Copyright ©2009 David S. Janzen

    Your Code

    Spring Overview• Spring is a lightweight framework for building Java

    applications (Spring Home: http://www.springsource.org/)

    • Any application (web, GUI, …)

    • Lightweight means minimal impact to your code

    • Spring is based on the principle of Inversion of Control

    • Rather than class A declaring an instance of class B,

    Class A

    Class B

  • Copyright ©2009 David S. Janzen

    Your Code

    Spring

    Spring Overview• Spring is a lightweight framework for building Java

    applications

    • Any application (web, GUI, …)

    • Lightweight means minimal impact to your code

    • Spring is based on the principle of Inversion of Control

    • Rather than class A declaring an instance of class B,

    some external process provides A with B

    Class A

    Class B

    Interface I

    Container

  • Copyright ©2009 David S. Janzen

    Spring Overview• Dependency Injection is the run-time injecting of

    dependencies

    Your Code

    SpringClass A

    Class B

    Interface I

    Container

    dependency

  • Copyright ©2009 David S. Janzen

    POJO: Plain Old Java Objectpublic class Person {

    private String firstName;

    private String lastName;

    public String getFirstName() {

    return firstName;

    }

    public void setFirstName(String firstName) {

    this.firstName = firstName;

    }

    public String getLastName() {

    return lastName;

    }

    public void setLastName(String lastName) {

    this.lastName = lastName;

    }

    }

    Your Code

    Class A

    Person

    Interface I

  • Copyright ©2009 David S. Janzen

    Another POJOpublic class Book {

    private int isbn;

    private String title;

    private Person author;

    public void setIsbn(int i) {

    isbn = i;

    }

    public void setTitle(String t) {

    title = t;

    }

    public void setAuthor(Person a) {

    author = a;

    }

    public Person getAuthor() {

    return author;

    }

    }

    Your Code

    Book

    Person

    Interface I

  • Copyright ©2009 David S. Janzen

    Typical Clientpublic class Client {

    public static void main(String [] args) {

    Person p = new Person();

    Book b = new Book();

    p.setFirstName(“David”);

    p.setLastName(“Janzen”);

    b.setIsbn(123456789);

    b.setTitle(“TDD for Dummies by Dummies”);

    b.setAuthor(p);

    }

    }

  • Copyright ©2009 David S. Janzen

    Dependency Injection with Spring

    • Spring provides a container that will

    • Construct objects

    • Populate object fields

    • Inject references between objects

    • You wire the objects together through a configuration

    file such as xml

  • Copyright ©2009 David S. Janzen

    Setter Injection• Declaration of a bean instantiates an object

    • Values can be injected into the object

  • Copyright ©2009 David S. Janzen

    Injecting Other Beans

    123456789

    TDD for Dummies by Dummies

  • Copyright ©2009 David S. Janzen

    Constructor Injection• Constructor-arg tag is used to pass dependency via

    constructor

    David Janzen

    public class Person {

    private String name;

    public Person(String name) {

    this.name = name;

    }

    public String getName() {

    return name;

    }

    }

  • Copyright ©2009 David S. Janzen

    Multi-Type Constructor Injection• What if two constructors have an argument of

    different types?

    • Constructor-arg tag can specify a type

    24

    public class Person {

    private String name; private int age;

    public Person(String name) { this.name = name; }

    public Person(int age) { this.age = age; }

    }

    Invokes String constructor

    24

  • Copyright ©2009 David S. Janzen

    Multi-Arg Constructor Injection• We can specify the order of constructor arguments

    with index

    David

    Janzen

    public class Person {

    private String firstName, lastName;

    public Person(String fname, String lname) {

    this.firstName = fname;

    this.lastName = lname;

    }

    }

  • Copyright ©2009 David S. Janzen

    Wiring beans in XML

    � Root element is

    � Contains one or more elements

    � Beans can be named by▪ id

    ▪ name (used as name if no id given)

    ▪ class (fully-qualified classname used as name if no id or name given)

    Preferred because XML editors can verify this

  • Copyright ©2009 David S. Janzen

    Bean Name Aliasing

    � Beans can have multiple names

    ▪ First is default

    ▪ Could aid in maintenance

    ▪ Ex. consolidate two classes into one

  • Copyright ©2009 David S. Janzen

    Typical Spring Application

    POJI/POJO

    Spring BeanFactory

    Bean Wiring

    main() or Servlet

  • Copyright ©2009 David S. Janzen

    Spring Overview• Spring acts more like a container than a framework

    • Constructs instances of classes

    • With desired dependencies (DI)

    • Integrates with data access options

    • JDBC or ORM (Hibernate, iBATIS, JDO)

    • Transaction management

    • Web MVC

    • Aspect oriented programming

    • Remoting

    • E-Mail support

    • Job scheduling support

  • Copyright ©2009 David S. Janzen

    Spring Organization

    Diagram from “Spring in Action” by Walls and Breidenbach

  • Copyright ©2009 David S. Janzen

    Spring Packages

    Spring’s MVC frameworkspring-webmvc.jar

    Most of above w/o mocksspring.jar

    Struts integration, file upload, …spring-web.jar

    Extend dao for Hibernate, other ORMsspring-orm.jar

    Mocks to aid in testingspring-mock.jar

    Data access with JDBC, transactionsspring-dao.jar

    Basic DI supportspring-core.jar

    Extensions, remoting,…spring-context.jar

    Aspect-oriented programmingspring-aop.jar

    ContainsJar File

  • Copyright ©2009 David S. Janzen

    Declarative vs. Programmatic• Most Spring facilities can be configured in either a

    declarative or programmatic way

    • Declarative generally means the configuration is defined

    in a file (XML, properties, …)

    • Programmatic generally means the configuration is

    defined in software

    • Declarative configuration allows you to make changes

    to the system without recompiling

  • Copyright ©2009 David S. Janzen

    Exercise Preparation• Examine BooksMap files

    • Read TestBooksMap.java carefully

    • Examine run.sh

    • Run run.sh

    • Examine testTitlesMapbean.xml

    • Examine coverage.txt

  • Copyright ©2009 David S. Janzen

    Exercise• Retrieve the BooksMap example from

    http://users.csc.calpoly.edu/~djanzen/courses/509S09/BooksMap.tar

    • Untar in a directory on vogon

    tar xvf BookMaps.tar

    • Ensure that all tests pass

    • Add another test or two to TestBooksMap.java

    • Create a new book and check that it exists

    • Stretch: What happens if you ask for a book that is

    not in the map?

    • What is different about the third test

    (testBookTitlesAutoWire)? Add a second Person in this

    test. What happens?

  • Copyright ©2009 David S. Janzen

    Singleton Bean Instantiation� By default, all beans are singletons

    ▪ So calling getBean() always returns the same one

    public class TestPerson {

    @Test public void testSingleton() {

    try {

    //write testSingletonbeans.xml

    XmlBeanFactory factory =

    new XmlBeanFactory(new FileSystemResource("testSingletonbeans.xml"));

    Person p1 = (Person)factory.getBean("jd");

    Person p2 = (Person)factory.getBean("jd");

    assertEquals(p1.getFirstName(),"John");

    assertEquals(p2.getFirstName(),"John");

    assertTrue(p1 == p2);

    assertTrue(p1.getFirstName().equals(p2.getFirstName()));

    assertTrue(p1.getLastName().equals(p2.getLastName()));

    John

    Doe

  • Copyright ©2009 David S. Janzen

    Non-Singleton Bean Instantiation� The instantiation mode can be changed

    ▪ Specify singleton=“false”

    public class TestPerson {

    @Test public void testNonSingleton () {

    try {

    //write testSingletonbeans.xml

    XmlBeanFactory factory =

    new XmlBeanFactory(new FileSystemResource("testSingletonbeans.xml"));

    Person p1 = (Person)factory.getBean("jd");

    Person p2 = (Person)factory.getBean("jd");

    assertEquals(p1.getFirstName(),"John");

    assertEquals(p2.getFirstName(),"John");

    assertTrue(p1 != p2);

    assertTrue(p1.getFirstName().equals(p2.getFirstName()));

    assertTrue(p1.getLastName().equals(p2.getLastName()));

    John

    Doe

  • Copyright ©2009 David S. Janzen

    ApplicationContext

    � See JavaDocs for ApplicationContext

    � Everything we know about BeanFactory we can apply to ApplicationContext

  • Copyright ©2009 David S. Janzen

    Stand-alone ApplicationContext

    POJI/POJO

    ApplicationContext

    Bean Wiring

    client

  • Copyright ©2009 David S. Janzen

    Web ApplicationContext

    POJI/POJO

    ApplicationContext

    Bean Wiring

    servlet

    Automatically loaded

  • Copyright ©2009 David S. Janzen

    Spring MVC Architecture

    Dispatcher Servlet

    Controller

    View

    Model

    Based on http://www.springframework.org/docs/MVC-step-by-step/Spring-MVC-step-by-step.html by Thomas Risberg

    See sample of files in WebMVC

  • Copyright ©2009 David S. Janzen

    Configuring web.xml� war/WEB-INF/web.xml (applicationContext.xml)

    springapp

    org.springframework.web.servlet.DispatcherServlet

    1

    springapp

    *.htm

    index.jsp

    Route all *.htm to this servlet

    Identify a Spring DispatcherServlet

  • Copyright ©2009 David S. Janzen

    Configuring DispatcherServlet

    Dispatcher Servlet

    Controller

    View

    Model

    build.xml build.properties

    web.xml

  • Copyright ©2009 David S. Janzen

    Configuring springapp-servlet.xml� war/WEB-INF/springapp-servlet.xml

    springappController

    Map hello.htm to springappController

    Identify a controller

  • Copyright ©2009 David S. Janzen

    Configuring a Controller

    Dispatcher Servlet

    Controller

    View

    Model

    build.xml build.properties

    web.xmlspringapp-servlet.xml

  • Copyright ©2009 David S. Janzen

    Configuring libraries

    � Create a lib folder under war/WEB-INF

    � Copy the follow jars from where you extracted

    the Spring download to war/WEB-INF/lib

    ▪ spring.jar (from spring-framework-1.2.3/dist)

    ▪ commons-logging.jar (from spring-framework-

    1.2.3/lib/jakarta-commons)

    ▪ log4j-1.2.9.jar (from spring-framework-1.2.3/lib/log4j)

  • Copyright ©2009 David S. Janzen

    Creating the Controller� src/SpringappController.javaimport org.springframework.web.servlet.mvc.Controller;

    import org.springframework.web.servlet.ModelAndView;

    import javax.servlet.ServletException;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

    import java.io.IOException;

    public class SpringappController implements Controller {

    public ModelAndView handleRequest(HttpServletRequest request,

    HttpServletResponse response)

    throws ServletException, IOException {

    return new ModelAndView("");

    }

    }

  • Copyright ©2009 David S. Janzen

    Configuring a View

    Dispatcher Servlet

    Controller

    View

    Model

    build.xml build.properties

    web.xmlspringapp-servlet.xml

    SpringappController.java

    hello.htm

  • Copyright ©2009 David S. Janzen

    Creating a View

    � Create the file hello.jsp in war

    � Include something like this in hello.jsp

    My First Spring Application

    My First Spring Application

    Isn't this cool.

    You entered hello.htm.

    The DispatcherServlet noticed it was a *.htm request

    (according to web.xml) ...

    so it mapped the request to the SpringappController (as

    defined in springapp-servlet.xml).

    SpringappController logged what was happening then returned

    the view "hello.jsp“ and voila, here we are!

  • Copyright ©2009 David S. Janzen

    Set View in Controller� Modify SpringappController.java in src

    import org.springframework.web.servlet.mvc.Controller;

    import org.springframework.web.servlet.ModelAndView;

    import javax.servlet.ServletException;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

    import java.io.IOException;

    public class SpringappController implements Controller {

    public ModelAndView handleRequest(

    HttpServletRequest request, HttpServletResponse response)

    throws ServletException, IOException {

    return new ModelAndView("hello.jsp");

    }

    }

  • Copyright ©2009 David S. Janzen

    Configuring a View

    Dispatcher Servlet

    Controller

    View

    Model

    build.xml build.properties

    web.xmlspringapp-servlet.xml

    SpringappController.java

    hello.jsp

    hello.htm

  • Copyright ©2009 David S. Janzen

    Modify Modelpublic class SpringappController implements Controller {

    private ProductManager prodMan;

    public ModelAndView handleRequest(

    HttpServletRequest request, HttpServletResponse response)

    throws ServletException, IOException {

    String now = (new java.util.Date()).toString();

    Map myModel = new HashMap();

    myModel.put("now", now);

    myModel.put("products",

    getProductManager().getProducts());

    return new ModelAndView("hello", "model", myModel);

    }

    public void setProductManager(ProductManager pm){

    prodMan = pm;

    }

    public ProductManager getProductManager() {

    return prodMan;

    }

  • Copyright ©2009 David S. Janzen

    View can access Model

    Products

    $


    Increase Prices


  • Copyright ©2009 David S. Janzen

    Business Data in Model

    Dispatcher Servlet

    Controller

    View

    Model

    build.xml build.properties

    web.xmlspringapp-servlet.xml

    SpringappController.java

    hello.jsp

    hello.htm

    Product.javaProductManager.java

  • Copyright ©2009 David S. Janzen

    Testing Controller and Model

    Dispatcher Servlet

    Controller

    View

    Model

    build.xml build.properties

    web.xmlspringapp-servlet.xml

    SpringappController.java

    hello.jsp

    hello.htm

    Product.javaProductManager.java

    TestProductManager.java

    TestSpringappController.java

    springapp-servlet.xml

  • Copyright ©2009 David S. Janzen

    Adding a Controller and Validator

    Dispatcher Servlet

    Controller

    View

    Model

    build.xml build.properties

    web.xmlspringapp-servlet.xml

    SpringappController.java

    hello.jsp

    hello.htm

    PriceIncreaseValidator.java

    ProductManager.java

    PriceIncreaseFormController.java

    priceincrease.jsp

    PriceIncrease.java

    priceincrease.htm

    messages.properties

  • Copyright ©2009 David S. Janzen

    Spring Resources

    � www.springsource.org

    � Professional Java Development with the Spring Framework

    � Spring in Action

    � Pro Spring