Chapter 2. Introducing Spring

Spring is a Java framework that emerged to address many of the shortcomings present in the initial versions of the de facto Java platform targeting the enterprise market or server-side space: J2EE (Java 2 Enterprise Edition), today just Java EE. In this sense, Spring is a true grassroots movement that came about from two best practices books on this platform entitled J2EE Design and Development[5] and J2EE Development without EJB.[6]

To one of the authors of these books—Rod Johnson, who was Spring's lead architect—there were many complexities that needed to be addressed in order to embark on a server-side Java project using J2EE. Chief among these complexities was EJB (as implied by one of these titles), and the principles that emerged for designing applications without EJBs became the foundation of the Spring Framework.

While the landscape in server-side Java development has changed remarkably since the ideas underpinning Spring emerged, with the flagship enterprise Java platform undergoing three major revisions (J2EE 1.3, J2EE 1.4, and Java EE 5) and the "black sheep" in question, EJB, also being revamped the same number of times, Spring has continued to strike a chord with many Java practitioners dedicated to server-side development.

Today, Spring is considered a one-stop shop, or full stack, for all the needs encountered in the development life cycle of an enterprise Java project, providing everything from its own Model-View-Controller (MVC) module, which is a common paradigm used in server-side developments, to tight support of object-relational mapping tools, which are pretty much the norm for bridging Java objects to the relational database world that dominates enterprise IT data centers. Equipped with this brief background and awareness of the place Spring holds in the Java ecosystem, let's explore the technical foundations of Spring.

Spring Concepts and Architecture

Software applications are generally chock-full of dependencies, whether to another application, an external resource, or some other type of mechanism. Each of these dependencies helps to make an application "tick" the way you intended it to. If you drill down deep enough at the code level—in the Java classes themselves—you will find that this same behavior continues to hold true.

You may find a few Java classes depend on the use of some third-party API, others on an external resource like a database connection, and yet others on an inheritance hierarchy imposed by some other classes. So you could effectively say dependencies are everywhere, but while these dependencies in themselves are necessary to achieve the ultimate goal of a functioning application, the way you go about defining them can have broad implications in the overall design of an application.

Take for instance the classes presented in Listings 2-1 and 2-2, both of which illustrate how to reference an external resource, or define a dependency. They differ, however, in the way this is done.

Example 2-1. Defining Resource Dependencies in Java

public class Sales {

    public double getMonthlySales(String month) {
        InitialContext ctx = new InitialContext();
        DataSource ds = (DataSource) ctx.lookup("java:comp/enb/jdbc/mysql");

        Connection conn = ds.getConnection();


       try {
           Statement stm = conn.createStatement();
           // Extract actual monthly sales
           return monthlySales;
       } catch (SQLException e) {
           // Handle error

       } finally {
           conn.close();
       }
    }

}

Example 2-2. Defining Resource Dependencies in Java via Dependency Injection

public class Sales {
    private DataSource ds;

    public void setDataSource(DataSource ds) {
        this.ds = ds;
    }
public double getMonthlySales(String month) {
      Connection conn = this.ds.getConnection();

     try {
         Statement stm = conn.createStatement();
         // Extract actual monthly sales
         return monthlySales;
     } catch (SQLException e) {
         // Handle error


     } finally {
         conn.close();
     }
  }

}

Notice how the class in Listing 2-1 relies on an explicit lookup sequence that requires the use of an API—the JNDI API—while the one in Listing 2-2is apparently devoid of any such mechanism, relying solely on the use of a method to gain access to the same DataSource. In reality, the Java class in Listing 2-2is gaining access to the same resource as the one in Listing 2-1, except it's obtaining the resource characteristics from another location. How can this be so? Through Inversion of Control.

Inversion of Control and Dependency Injection

Inversion of Control (IoC) is a software design pattern in which the flow of a system is inverted with respect to a traditional sequence of procedural calls; the flow is instead delegated over to an external entity, which then performs the sequence of calls based on a predefined set of instructions.[7]

In Spring's case, it is said to be an IoC container since it's precisely Spring that fulfills the part of an external entity in the IoC definition sense. Spring implements a particular type of IoC, Dependency Injection (DI), which is the pattern illustrated in Listing 2-2. In light of this IoC definition, the differences between Listings 2-1 and 2-2 should become more evident. It's not that Listing 2-2 is devoid of dependencies, but rather that its dependencies are injected from an external entity—the Spring IoC container—that has been configured with a set of predefined values.

The actual injection of values takes place when an object of the corresponding class is instantiated, either via its constructor method or setter methods—as is the case in Listing 2-2 using a setter method.

This is in contrast to Listing 2-1, in which the class itself takes responsibility for accessing the resource, therefore requiring a traditional sequence of procedural calls. DI can be used to tackle many types of dependencies in Java classes, not just resources as illustrated in Listing 2-2. For example, another case of DI could consist of a business service being injected into another business service, avoiding code dependencies between each service to be intertwined in the same location.

DI effectively allows you to simplify the thought process for designing programs, since you don't have to think of multiple sequences that need to be fulfilled at once, but rather individual sequences that can later be injected into certain locations of a program.

If you are new to developing enterprise applications, you may not see an immediate benefit to using DI until you immerse yourself in a typical enterprise-level project.

For the most part, enterprise applications are full of dependencies in the form of services and resources that are closely intertwined with the business logic they attempt to fulfill; things like data sources, transactions, security, and logging data are all carefully coordinated aspects that are taken into account in projects of this nature.

Were it not for the sheer size and life span of enterprise applications, using something like DI might be seen as a purely academic practice, but it is exactly the size and constant flux of enterprise projects that has given Spring and its DI approach an important market share in the area of enterprise Java projects.

By effectively separating business logic from all its underlying services and resources, a project's code base is kept increasingly clean, favoring what are four important characteristics in enterprise software: simplicity, maintenance, testing, and reusability.

Which takes us to another construct central to Spring that fosters these last characteristics: Plain Old Java Objects (POJOs).[8]

Plain Old Java Objects

A POJO is an object instantiated from a Java class that possesses a few of the following technical characteristics:

  • It has numerous properties/fields.

  • Its properties/fields are accessed and assigned via getter and setter methods, respectively.

  • It may have other methods containing business logic, for manipulating either its properties/fields or other resources.

At first glance, these behaviors might seem strikingly similar to those of a Java Bean—as defined by the Java platform—and in fact, they have the same characteristics. So why not just say Java Bean and be done with it? Why POJO?

The term "POJO" started being thrown around when the original Java EE platform showcased its first versions of Enterprise Java Beans (EJBs). In order to differentiate from this last Java Bean incarnation, which is a completely different beast from a run-of-the-mill Java Bean, many started prefixing the "Plain Old" phrase when referring to non-EJB objects.

Further defining the term POJO was the fact that EJBs required the use of a nonstandard JVM life-cycle contract. A nonstandard life cycle implies that a Java object is required to go through certain steps not defined by a JVM—such as create, remove, activate, and passivate—that were a requirement in EJB objects. And by contract, it is to be understood that an EJB class needed to implement an interface defined by the EJB standard—the framework—in order to enforce this special life cycle.

Ever since then, the definition has taken on a life of its own, making POJOs a household name in the area of enterprise Java applications. So far you've seen a POJO's technical characteristics enumerated; next you will learn more about its behavioral characteristics.

Simplicity

It should be somewhat obvious that "Plain Old" goes hand in hand with simplicity. In a POJO's case, its most clear traces of simplicity come through with its often scant use of third-party APIs and light reliance on class inheritance hierarchies.

This is not to say a POJO can't or doesn't use third-party APIs, but more often than not, a POJO's import statements are reduced to either a few classes in the core Java SE platform or limited to a few constructs from some third-party library.

Similarly, most POJOs don't have deep inheritance hierarchies as is often the case with some object-oriented (OO) designs. With respect to interfaces, POJOs never rely on any framework interfaces that might tie them to a nonstandard life cycle, as outlined earlier. If employed at all, interfaces in POJOs are used to enforce business method contracts.

While it may indeed be a slippery slope to characterize a POJO by its number of import statements or its inheritance hierarchy, as a colleague once put it, "If at first glance a class doesn't look simple, needless to say it isn't a POJO," and there is nothing like the use of too many APIs or deep inheritance hierarchies to make a class look complicated even to the trained eye.

Maintenance

For the massive undertaking that is developing enterprise-grade applications, most projects of this nature portray a considerable investment to any organization and are seen as a critical business asset once placed in production, hence maintenance proves to be an important factor with the natural changing of business requirements.

When it comes to enterprise applications, it's not strange for numerous groups of people—internal employees or contractors—to work on the same application. Add to this the effective life span of most applications is in terms of years, and maintenance can prove to be a nightmare if different people are brought in to modify an overly complex code base.

The point here is that the kiss of death to maintenance is complexity, and in software development, we can draw from the well-known acronym KISS—keep it short and simple.

It doesn't matter if a code wizard's über-class concoction can shave days off a project's schedule. When maintenance or upgrade time comes around, having a code base composed of POJOs—even if this requires lengthier times—will pay off handsomely, not only because POJOs will allow different people to navigate a code base more easily, but also because it favors another important aspect to software development: testing.

Testing

In any software application, errors are something that users and development teams have come to live with; in thousands of lines of code, there is a high probability that buried amidst all the logic is some unforeseen sequence of calls that will break the intended purpose of an application. To solve this nuisance, testing has proven to be the most effective solution.

However, the issue with testing is that it's often a continuous process. More testing will tend to uncover more unforeseen behaviors, though it's a known fact that the sooner these unforeseen behaviors—errors—are uncovered, the less disruptive and expensive they become.

Until recently, most software testing took place once the first end users got their hands on a piece of software; however, a new approach named test-driven development[9] started to make its way into the development world. This approach consisted of testing code at the same time classes were being written, effectively shifting testing to one of the earliest possible phases in the life span of an application.

Test-driven development proves easiest to implement when applied to POJOs, due to their minimalistic approach and limited number of dependencies—especially dependencies on infrastructure resources.

In order to perform testing, it's critical to replicate everything a class would use in a production system. As a consequence, if a class depends on infrastructure resources, like a data source, or it depends on a nonstandard JVM life cycle, like an EJB that requires its own environment, testing can become difficult. Hence, it's much easier to write a test for a potential outcome when a class's logic is less convoluted with dependencies, like it is in POJOs.

Similarly, such tests at a class level also serve the purpose of "safety nets" once a project's code base starts being modified. By having such tests, each time an application is modified it can be checked against these benchmarks, guaranteeing that earlier logic contained in a class has not been compromised due to some unintended modification in the code base.

Testing is an extremely ample subject, and I won't even attempt to summarize all its benefits here. The objective was simply to emphasize that POJOs lend themselves extremely well to the whole testing paradigm, something that will become more evident once you create your first Spring application in the upcoming section.

Reusability

Reusability is one of the many goals pursued in OO projects, but it can be hard to achieve. The reason reusability proves difficult is because classes often fulfill too many duties in an OO project. This not only causes reusable logic to be obscured in large classes, but also breeds the mentality of "It's easier to rewrite it than to learn how to use it" given the complexity of some classes.

While reusability is undeniably linked to getting a project's "big picture" from the outset, there are many factors that foster it, and one of them is POJOs. Since POJOs themselves foster simplicity, this has the side effect of smaller and more understandable classes, which in turn favor reusability.

POJOs force a developer to think in terms of more manageable units and not get carried away with what a single class attempts to fulfill. This benefits not only an individual developer's efforts to reuse classes, but also the efforts of an entire team that can clearly understand a class's logic and therefore reuse it more easily. Having described a POJO's primary characteristics, let's finish the discussion on Spring's concepts and architecture with a look at the numerous parts that make up Spring.

Spring Portfolio

Spring's popularity has seen it blossom from a grassroots project in the Java community to a federated portfolio of projects spanning beyond the Java platform. Table 2-1 presents a summary of the various projects that comprise the Spring portfolio.

Table 2-1. Spring Portfolio Projects

Project[a]

Function

Home Page

[a]

Spring Framework (Core)

The core framework, Spring's main offering

http://www.springsource.com/products/springframework

Spring Security

Project that provides authentication and authorization services for enterprise applications based on Spring tenets

http://www.springsource.com/products/springsecurity

Spring Web Flow

A web application front-end framework based on Spring principles

http://www.springframework.org/webflow

Spring Web Services

A framework designed to make the management of SOAP and Plain Old XML (POX) web services easier

http://www.springsource.com/products/springwebservices

Spring Dynamic Modules for OSGi

Project designed to make use of OSGi features in Spring

http://www.springsource.com/products/springdynamicmodules

Spring Batch

A batch-processing framework based on Spring principles

http://www.springsource.com/products/springbatch

Spring IDE

A set of GUIs for Spring configuration files, built as Eclipse plug-ins

http://www.springsource.com/products/springide

Spring Modules

A collection of tools, add-ons, and modules to extend the Spring Framework

https://springmodules.dev.java.net/

Spring Java Configuration

Project that provides a typesafe, pure-Java option for configuring the Spring IoC container

http://www.springframework.org/javaconfig

SpringBeanDoc

Project that facilitates documentation and graphing of Spring bean factories and application context files

http://spring-beandoc.sourceforge.net/

Spring .NET

Project for the .NET Framework, based on the same principles as its Java counterpart

http://www.springsource.com/products/springdotnet

Spring LDAP

An LDAP library based on Spring principles

http://www.springframework.org/ldap

Spring Rich Client

Project designed to leverage Spring's approach to the development of rich clients

http://www.springframework.org/spring-rcp

Spring Integration

Project designed to address Enterprise Integration Patterns in the context of Spring applications

http://www.springsource.com/products/springintegration

SpringSource dm Server

A module-based Java application server designed to leverage Spring, Apache Tomcat, and OSGi

http://www.springsource.com/products/suite/applicationplatform

[a] http://www.springframework.org/projects

This book will cover every aspect related to the Spring Dynamic Modules for OSGi project and also introduce the SpringSource dm Server, the latter of which facilitates the use of OSGi and Spring technology in the enterprise.

However, before we get to those subjects, it's important for you to get a feel for what the Spring platform can accomplish without the use of OSGi and have a firsthand account on the use of POJOs; IoC, DI, and testing, among other core subjects related to Spring. Up next you will embark on the task of creating a Hello World application using Spring.

Spring Hello World Application

The Hello World application you are about to start will take you through the most basic steps in using Spring, such as defining your domain model and POJOs, to more advanced topics, such as connecting to a relational database using Object-Relational Mapping (ORM) principles and making use of the MVC pattern to enable applications on the Web.

Be advised that this is a "show it all" Hello World example on the Spring Framework, and not your typical one-line Hello World program. This is done with good reason, since the integration between OSGi and Spring requires an understanding on all the subjects presented in this example.

Though the following Hello World application might take you a little longer to re-create than most Hello World examples, it will save valuable time and effort if you are not familiar with Spring, since the application is the essence of entire books covering the Spring Framework.

Figure 2-1 illustrates the different layers and components that will make up this application using the Spring Framework.

Spring Hello World application layers and components

Figure 2-1. Spring Hello World application layers and components

Prerequisites and Downloads

Table 2-2 lists the software you will need to download and install prior to embarking on your first Spring application.

Table 2-2. Spring Hello World Prerequisites and Downloads

Software

Function

Download Site

Java SE 5 or higher

Java's runtime environment

http://java.sun.com/javase/downloads/index.jsp

Java Ant 1.6 or higher

Popular Java build project, used for easing the compilation and creation of Spring applications

http://www.apache.org/dist/ant/binaries/apacheant-1.7.1-bin.zip

Spring Framework 2.5.4 (with dependencies)

Spring Framework's core libraries

http://www.springframework.org/download

Spring Web Flow 2.0.2

Project that aids in the creation of Java web applications using Spring's MVC paradigm

http://www.springframework.org/download#webflow

Apache Tiles 2.0.6

Web templating system used to incorporate Asynchronous JavaScript and XML (AJAX) functionality into Spring MVC designs

http://tiles.apache.org/download.html

Apache Tomcat Core 5.5.26

Java container for deploying applications on the Web

http://www.apache.org/dist/tomcat/tomcat-5/v5.5.26/bin/apache-tomcat-5.5.26.zip

Java Persistence API (JPA) reference implementation 1.0

Java's de facto ORM API for persisting Java objects to a Relational Database Management System (RDBMS)

Included in the Spring Framework with dependencies download

MySQL Community Server 5.0

An open source RDBMS

http://dev.mysql.com/downloads/mysql/5.0.html

MySQL Connector/J Driver 5.1

MySQL-Java driver

http://dev.mysql.com/downloads/connector/j/5.1.html

HSQLDB 1.8

A lightweight in-memory RDBMS used for testing

Included in the Spring Framework with dependencies download

JUnit 4.4

Java framework used for unit testing

Included in the Spring Framework with dependencies download

It's very likely you may have some of this software already installed on your workstation; if so, just ensure that you have the suggested versions, as minor version variations may hold you back in getting through the outlined steps.

Additionally, since some of this software was already used in the OSGi Hello World application presented in Chapter 1, installation instructions for those packages will not be presented here, so please refer to Chapter 1 for detailed installation instructions.

Installing Spring Framework

The process for installing the Spring Framework consists of just one step: unzipping the downloaded file into a directory of your choice. As mentioned earlier, Spring consists of numerous parts, many of which I can't talk about in this introductory application, so while you are free to browse and explore on your own, it's only the following directories and files that will be of interest to you:

  • dist: Contains the main distribution file spring.jar used by every Spring application.

  • modules (inside dist):Includes the numerous modules that form part of the Spring distribution. Among the ones used in this application will be spring-webmvc.jar and spring-orm.jar

  • lib: Contains the various dependencies used by Spring, many of which are amply used in enterprise applications and will also serve your Hello World application, among them JUnit, JPA, and HSQLDB.

Installing Apache Tomcat

The process for installing Apache Tomcat also consists of one step: unzipping the downloaded file into a directory of your choice. Once you do this, descend into the unzipped directory and perform the following test.

While in Apache Tomcat's bin directory, execute java -jar bootstrap.jar; this will start Apache Tomcat under port 8080. Next, open a browser and attempt to access the address http://localhost:8080/; you should see an Apache Tomcat Welcome page. In case this test fails, verify that port 8080 is not busy: check that no other application is running on the same default port (8080) as Apache Tomcat.

Installing MySQL

Depending on your operating system, follow the instructions included in your download, which can vary from those given in a simple Installation Wizard on Windows, to executing a few scripts on Unix-type systems. Once you have installed MySQL's base system, you will need to create a database in order to place your application data. Follow these steps:

  1. Create a database: execute the command mysqladmin create springosgi, which will create a database instance by the name springosgi.

    Note

    You may be required to introduce MySQL's root password to create a new database. Use the following command if this is the case: mysqladmin -u root -p<rootpassword> create springosgi.

  2. Create/Grant privileges to an application user: log in to the main database—mysql—with the command mysql -u root -p<rootpassword> -D mysql, and then execute the instructions GRANT ALL PRIVILEGES ON springosgi.* to hello@localhost IDENTIFIED BY 'world'. This process will grant connection rights to the user hello with the password world on the springosgi database, credentials that will be used to connect from Java to MySQL.

  3. To ensure that the proper connection rights have been established, execute the following command from a command prompt: mysql -u hello -pworld -D springosgi. Upon performing this instruction, you should be placed inside a MySQL shell.

  4. In case this test fails, verify springosgi database credentials: ensure that the user/password credentials for the database were granted as outlined in the previous steps.

Installing Remaining Downloads

The remaining downloads simply contain JAR files that will aid you in the creation of the Hello World application. Just take note of their location—you will move them around when the need arises.

Setting Up the Hello World "Playground" Directory Structure

Now that you've got the tools working, it's time to create the proper workspace in which to maneuver, a directory structured like the one illustrated in Figure 2-2.

The directory structure functions as follows:

  • build.xml: This is the main Java Ant configuration file containing the necessary tasks to build the application.

  • classes: All compiled Java classes are placed in this directory.

  • dist: All built applications are placed in this directory.

  • lib: All JARs needed to compile Java sources are placed in this directory.

  • src: All Java sources files composing the application are placed accordingly in subdirectories inside this directory, including application web descriptors in WEB-INF, metadata files in META-INF, and application user interfaces (like JSPs) in GUI.

Directory structure for the Hello World "playground"

Figure 2-2. Directory structure for the Hello World "playground"

The Domain Model

A domain model is used to describe a system's core competencies in terms of classes. Given the requirements of most Hello World examples, our domain model will be extraordinarily simple, consisting of just two classes: one used to associate "Hello World" messages in different languages, and another to associate a person performing the translation of each "Hello World"message.

In OO modeling terms, the domain model will consist of a single one-to-one relationship: each "Hello World" message will have one person, and consequently, each person will also have one "Hello World" message. Listing 2-3 illustrates the HelloWorld class, whileListing 2-4 contains the Person class.

Example 2-3. HelloWorld.java POJO

package com.apress.springosgi.ch2.hello;

import java.util.Date;

public class HelloWorld {

    private long id;
    private String language;
    private String message;
    private Date transdate;
    private Person translator;

    public HelloWorld(String language, String message, Date transdate,
HelloWorld.java POJO
Person translator) { this.language = language; this.message = message; this.transdate = transdate; this.translator = translator; } public HelloWorld() { } public void setId(long id) { this.id = id; } public long getId() { return id; } public void setLanguage(String language) { this.language = language; }
public String getLanguage() {
        return language;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setTransdate(Date transdate) {
        this.transdate = transdate;
    }

    public Date getTransdate() {
        return transdate;
    }

    public Person getTranslator() {
        return translator;
    }

    public void setTranslator(Person translator) {
        this.translator = translator;
    }

  }

Example 2-4. Person.java POJO

package com.apress.springosgi.ch2.hello;

public class Person {

    private long id;
    private String firstName;
    private String lastName;
    private double hourlyRate;
public Person(String firstName, String lastName, double hourlyRate){
        this.firstName = firstName;
        this.lastName = lastName;
        this.hourlyRate = hourlyRate;
    }

    public Person() {
    }

    public double getHourlyRate() {
        return hourlyRate;
    }

    public void setHourlyRate(double hourlyRate) {
        this.hourlyRate = hourlyRate;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

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

    public long getId() {
        return id;
    }
 }

Both class listings are in line with the POJO characteristics outlined earlier: each class has numerous fields, possesses various getter and setter methods to access and assign values to each field, and contains no framework-specific interfaces.

Also notice that at this juncture, there is no indication as to what objects of either the HelloWorld or Person class will do. Will they be presented on a web page? Will they be persisted to a database? Will they be presented on a desktop GUI? This is the whole point of using POJOs and Spring's IoC—having API-agnostic code with all the benefits mentioned in the last section.

Now, these two classes by themselves only represent the application's objects and their corresponding properties, but what about the application's actions? For that, you will need to define a service interface containing all the possible actions on this pair of objects. Listing 2-5 illustrates such an interface.

Example 2-5. HelloWorldService.java Interface

package com.apress.springosgi.ch2.hello;

import java.util.List;

public interface HelloWorldService {

    public HelloWorld findById(long id);

    public List<HelloWorld> findAll();

    public HelloWorld update(HelloWorld hw);

    public void save(HelloWorld hw);

    public void delete(HelloWorld hw);

    public void deleteMessage(long id);

    public List<HelloWorld> findByTranslatorFirstName(String firstName);

    public List<HelloWorld> findByTranslatorLastName(String lastName);

    public List<HelloWorld> findByTranslatorHourlyRateOver(double hourlyRate);

    public List<HelloWorld> findByLanguage(String language);
public List<HelloWorld> findByMessage(String message);
}

This last interface illustrates a typical contract for actions performed on class objects linked to a data store; things like the findByX search methods, as well as the update, save, and delete methods, are all indicative of some type of persistence operation being involved.

But still, aside from using the HelloWorld class as an input parameter and returning Java lists of HelloWorld objects in various methods, there is still no trace of how persistence or an RDBMS will be involved in the Hello World application.

So up next, we will explore how you would go about persisting the application's domain model using the JPA and how to create a Data Access Object (DAO) out of this last interface with the aid of the same JPA and Spring.

Persisting the Domain Model with JPA

A little background on the whole issue of persistence in Java may be in order to explain why JPA[10] was chosen for this application. If there is more than one way to skin a cat, the Java world has seen its fair share of cat skinning throughout the years for persisting data. Among these approaches you will find things like JDBC, JDO, Entity EJBs, Object-Relational Mappers (ORMs), and perhaps some other standards or home-brewed processes to achieve the same results.

Java aside, many in the object-oriented community have always favored the approach and results offered by ORMs for persisting objects to RDBMSs; however, until recently the issue with Java ORMs was that they were extremely fragmented, resulting in many contrasting ways of doing Object-Relational Mapping in the Java platform, that is, until JPA came to fruition.

JPA is now the standard API for performing Object-Relational Mapping in Java, and since its emergence, many Java ORM vendors have pegged their products against this API, with the biggest beneficiaries of this whole process being application developers, since a single and unified API can now be used across the board for object-relational purposes. This is why the Hello World application will use JPA.

Though the Hello World application will use a very basic set of JPA instructions, and Spring does an excellent job of abstracting away many direct uses of the API through its IoC/DI approach, be aware that JPA is an extensive technology in itself, with entire books written on the subject. That said, let's get started decorating the Hello World application POJOs with JPA annotations.

Listing 2-6 contains a modified version of the HelloWorld class decorated with JPA annotations.

Example 2-6. HelloWorld.java POJO with JPA Annotations

package com.apress.springosgi.ch2.hello;

import java.util.Date;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity
public class HelloWorld {

       @Id
       @GeneratedValue
    private long id;
       @Column
    private String language;

       @Column
    private String message;
       @Temporal(TemporalType.DATE)
    private Date transdate;
       @OneToOne(cascade = CascadeType.ALL)
    private Person translator;

    // Followed by methods identical to Listing 2-3
 }

The first thing to note about this listing is its various import statements, which represent JPA annotations and behaviors. Starting things off is the @Entity annotation used to decorate the class itself, indicating to the Java persistence runtime that the class represents an object that will be persisted using the JPA.

Immediately after, you find the remaining JPA annotations decorating the numerous fields belonging to the class. The @Id annotation indicates a class's field will be used as the primary key in a relational table, with the @GeneratedValue further specifying the strategy for the primary key, in this case a default strategy.

Next are two @Column annotations indicating the fields in question will be represented as columns in a relational table, with the @Temporal(TemporalType.DATE) serving the same purpose as the @Column annotation, except the former is specifically used for fields related to dates.

Finally, you find the @OneToOne annotation, which is used to represent a field's association to another class. In this case, the annotation indicates that the translator field is another entity class in the application, and hence has its own relational table. Of particular importance in this last annotation are its attributes,cascade = CascadeType.ALL,used to specify that any persistence operation occurring in the field be propagated out to its respective entity.

Listing 2-7 illustrates the other POJO used in the Hello World application decorated with JPA annotations.

Example 2-7. Person.java POJO with JPA Annotations

package com.apress.springosgi.ch2.hello;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Person {

       @Id
       @GeneratedValue
    private long id;
       @Column(name = "FNAME")
    private String firstName;
       @Column(name = "LNAME")
    private String lastName;
       @Column(precision=4, scale=2)
    private double hourlyRate;

    // Followed by methods identical to Listing 2-4
}

The JPA annotations used in the Person class are pretty much the same as the ones used in the HelloWorld class, with the exception of the attributes included in the @Column annotation. In this particular case, the attributes used in the @Column annotation override the default properties assigned to columns in a relational table, where name is used to indicate a specific column name, and precision along with scale are used to indicate a number column's characteristics.

An extremely important aspect to emphasize before moving on is that both these classes still remain POJOs. The JPA annotations allow each class's logic to remain free of any clutter needed to persist objects, relying instead on the runtime interpretation of such annotations to perform the actual persistence work, while maintaining a class structure that favors simplicity, maintenance, and testing. See the sidebar "POJOS and Annotations: Hot Button" for the controversy surrounding this definition of a POJO.

Though having these two JPA-decorated classes is an important part topersisting HelloWorld and Person objects, you're still in need of another important part of the puzzle in order to make use of such objects: a DAO.

Since both aforementioned classes persist objects to an RDBMS, a mechanism in which to retrieve such objects still needs to be established, and though you might not have realized it, you already set the groundwork for creating a DAO back in Listing 2-5, which defined the numerous actions the Hello World application would be able to perform.

Under normal circumstances, creating a class to serve as a DAO would entail not only implementing all the methods contained in an interface likethe one in Listing 2-5, but also extensive use of the JPA in order to perform the necessary logic against an RDBMS to obtain the desiredresults.

Fortunately, this is one area where Spring makes its presence felt with a very simple and straightforward manner of implementing a DAO. Listing 2-8 illustrates the HelloWorldDAO class using JPA and implementing the HelloWorldService interface defined in Listing 2-5.

Example 2-8. HelloWorldDAO.java DAO Class

package com.apress.springosgi.ch2.hello;

import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

import org.springframework.orm.jpa.support.JpaDaoSupport;

public class HelloWorldDAO extends JpaDaoSupport implements HelloWorldService {

    public HelloWorld findById(long id) {
        return getJpaTemplate().find(HelloWorld.class, id);
    }

    public List<HelloWorld> findAll() {
        return getJpaTemplate().find("select e from HelloWorld e");
    }

    public HelloWorld update(HelloWorld emp) {
        return getJpaTemplate().merge(emp);
    }

    public void save(HelloWorld emp) {
        getJpaTemplate().persist(emp);

    }

    public void delete(HelloWorld emp) {
        getJpaTemplate().remove(emp);
    }


    public List<HelloWorld> findByTranslatorFirstName(String firstName) {
        return getJpaTemplate().find("select e from HelloWorld e
HelloWorldDAO.java DAO Class
where e.translator.firstName = ?1", firstName); }
public List<HelloWorld> findByTranslatorLastName(String lastName) {
        return getJpaTemplate().find("select e from HelloWorld e where
HelloWorldDAO.java DAO Class
e.translator.lastName = ?1", lastName); } public List<HelloWorld> findByTranslatorHourlyRateOver(double hourlyRate) { return getJpaTemplate().find("select e from HelloWorld e where
HelloWorldDAO.java DAO Class
e.translator.hourlyRate > ?1", hourlyRate); } public List<HelloWorld> findByLanguage(String language) { return getJpaTemplate().find("select e from HelloWorld e where
HelloWorldDAO.java DAO Class
e.language = ?1", language); } public List<HelloWorld> findByMessage(String message) { return getJpaTemplate().find("select e from HelloWorld e where
HelloWorldDAO.java DAO Class
e.message = ?1", message); } @Transactional(propagation = Propagation.REQUIRED) public void deleteMessage(long id) { HelloWorld hw = getJpaTemplate().find(HelloWorld.class, id); getJpaTemplate().remove(hw); } }

The bulk of the work behind this DAO class is performed by the org.springframework.orm.jpa.support.JpaDaoSupport class and its getJpaTemplate().Notice that each of the class's methods contain calls to getJpaTemplate(), along with other nested calls to methods like persist(),merge(),delete(), and find(), which is accompanied by Java Persistence Query Language (JPQL), an SQL-esque syntax for Java.

In this scenario, the JpaDaoSupport class takes care of the intricacies of using the JPA, such as explicitly managing a persistence context and its corresponding JPA Entity Manager, as well as the handling of transactions. Hence, each call to getJpaTemplate() performs an atomic operation to whatever underlying data source is boundto the JPA Entity Manager.

The last method in the DAO class is different in the sense that it uses the transactional Spring annotation @Transactional(propagation = Propagation.REQUIRED), indicating that the operations included in the method will be performed under a single transaction. In this case, since the method is performing two operations against a data source—find and remove—this annotation overrides the default behavior of initiating a new transaction on each of the two calls made to getJpaTemplate().

This is all it takes to perform object-relational actions using Spring and JPA. Now you may be questioning where exactly this HelloWorldDAO class is getting its information, such as on what database to perform its queries. A very valid question, of course, but also one with a very simple answer: descriptors.

Descriptors for Spring and JPA

All the JPA annotations and queries presented in this section are of no use if an application is not aware of where to persist and find such objects; as a consequence, you need to rely on the use of XML descriptors to provide such information.

The JPA standard dictates that a descriptor by the name persistence.xml be used to contemplate all the JPA code contained in a set of classes, indicate an Entity Manager, RDBMS connection parameters, and classes to be persisted, among other things.

As you've already been forewarned, JPA is a very deep subject, and its corresponding persistence.xml file can also become elaborate; fortunately, since you're already relying on Spring to aid you in the implementation of a DAO using JPA, you can delegate much of the work in this file over to Spring.

Nevertheless, given that the JPA requires the use of a persistence.xml descriptor, you can't forgo this requirement, so you need to include a minimum set of instructions in such a file. Listing 2-9 contains the typical persistence.xml descriptor used in Spring applications employing JPA, which will also be used for the Hello World example.

Example 2-9. persistence.xml Used in JPA-Spring Applications

<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">

    <persistence-unit name="proSpringOSGiJpa" transaction-type="RESOURCE_LOCAL"/>

</persistence>

The remaining configuration parameters for using JPA in a Spring application are left in the hands of a service descriptor containing numerous Spring constructs. Listing 2-10 illustrates the helloworld-service.xml descriptor used in this Hello World application, with some of its values further explained in Tables 2-3 and 2-4 a little later in this section for cases in which different RDBMSs are used.

Example 2-10. helloworld-service.xml Used in the JPA-Spring Hello World Application

<?xml version="1.0" encoding="UTF-8"?<
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/
helloworld-service.xml Used in the JPA-Spring Hello World Application
spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/
helloworld-service.xml Used in the JPA-Spring Hello World Application
spring-tx-2.5.xsd"< <tx:annotation-driven/< <bean id="helloWorldService" class="com.apress.springosgi.ch2.hello.HelloWorldDAO"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </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.OpenJpaVendorAdapter"> <!-- See Table 2-3 for valid property values in this bean --> </bean> </property> <property name="loadTimeWeaver"> <bean class="org.springframework.instrument.classloading.SimpleLoadTimeWeaver"/> </property> </bean> <bean id="dataSource" class="<!-- See Table 2-4 for valid class values -->"> <!-- See Table 2-4 for valid property values in this bean --> </bean> <bean id="transactionManager" class="org.springframework.orm.jpa.Jpa
helloworld-service.xml Used in the JPA-Spring Hello World Application
TransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> <property name="dataSource" ref="dataSource"/> </bean> </beans>

The first thing to note about Listing 2-9 is its ample use of <bean> declarations, each having its own ID, as well as numerous properties to assign more specific behaviors to the bean in question. This is what most Spring configuration files look like; after all, Spring is mostly about enabling Java Beans—POJOs—with IoC/DI.

The initial bean declaration <bean id="helloWorldService"> is related to the DAO class you created earlier, associated through the class attribute with a value of com.apress.springosgi.ch2.hello.HelloWorldDAO.Inside the bean, however, you will find a property name and reference to entityManagerFactory, which indicates a dependence on another bean by this name that is charged with the management of entities.

Searching for a bean with an id value of entityManagerFactory, you will come to the second bean declaration in the file, the entityManagerFactory bean, which is associated to the class org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean, a Spring Framework factory class for JPA operations.

In terms of properties, this last bean is a little a more interesting than the first one, not only because it has three properties, but also because these properties are beans themselves. The meaning behind each of the properties in Spring's JPA Entity Manager factory are as follows:

  • dataSource:Defines the actual data source that is going to be managed by the factory, with its value pointing to yet another <bean> ID containing the data source's properties.

  • jpaVendorAdapter: Indicates the JPA vendor adapter used by the Entity Manager, which provides JPA behaviors like vendor-specific RBDMS mapping and SQLcreation strategies. Its value is another <bean>—in this case nested—pointing to the Spring-provided adapter class OpenJpaVendorAdapter (with other available Spring adapters classes being HibernateJpaVendorAdapter and EclipseLinkJpaVendorAdapter).The internal properties for the jpaVendorAdapter bean used in this application can be found in Table 2-3.

  • loadTimeWeaver: Provides the necessary weaving behaviors for using JPA with Spring, assigning the Spring-provided class org.springframework.instrument.classloading.SimpleLoadTimeWeaver.

Note

I will elaborate on the use and need of weaving toward the end of this chapter in the sidebar "What Is Weaving? And Why Is It Important?"

Amid the properties defined for the entityManagerFactory bean, recallthere was a property named dataSource pointing to a bean by the same name, which is precisely declared as the third top-level bean in the hellworld-service.xml descriptor.

Table 2-3. Spring Open JPA Vendor Adapter Bean Properties

Property

Values

Sample

Description

showSql

true/false

<property name=
"showSql"
value="true"/>

Outputs SQL in the log or console

generateDdl

true/false

<property name=
"generateDdl"
value="true"/>

Specifies whether to execute Data Definition Language (DDL) each time the Entity Manager is initialized, that is, whether to create and update the respective relational tables associated with each managed entity

databasePlatform

FirebirdDictionary,
H2Dictionary,
JDataStoreDictionary,
AccessDictionary,
OracleDictionary,
EmpressDictionary,
DBDictionary,
MyQSLDictionary,
HSQLDictionary,
InformixDictionary,
SQLServerDictionary,
InterbaseDictionary,
DB2Dictionary,
PointbaseDictionary,
SybaseDictionary,
FoxProDictionary,
DerbyDictionary,
PostgresDictionary
(all inside package
org.apache.openjpa.
jdbc.sql)
<property name=
"databasePlatform"
value="org.apache.
openjpa.jdbc.sql.
HSQLPlatform"/>

Indicates what specific platform to use for JPA mapping

Not to be confused with the JPA Entity Manager factory bean, which defines how to persist objects to a specific RDBMS, the data source bean defines where to persist such objects including an RDBMS's connection parameters. In Spring, there are two primary ways you can go about the process, as described in Table 2-4.

Table 2-4. Spring Data Source Bean Alternatives

Type

Class

Sample

Notes

Spring administered

org.springframework.
jdbc.datasource.
DriverManagerDataSource
<bean id="dataSource"
class="org.springframework.
jdbc.datasource.
DriverManagerDataSource">
<property
name="driverClassName"
value="org.hsqldb.jdbcDriver"/>
<property name="url"
value="jdbc:hsqldb:mem:
springosgi"/>
<property name=
"username" value="sa"/>
<property name="password"
value=""/></bean>

The data source is completely administered by Spring. In this case, the bean declares in-line properties related to the driver and username/password needed to connect to the RDBMS.

Externally administered

org.springframework.jndi.
JndiObjectFactoryBean
<bean id="dataSource"
class="org.springframework.
jndi.JndiObjectFactoryBean">
<property name="jndiName"
value="java:comp/env/jdbc/
springosgi" /></bean>

The data source is administered externally; Spring simply accesses the data source via the provided JNDI name. In this case, it's a Java application server/container that administers the data source and makes it available via JNDI, where the corresponding RDBMS properties—driver, username, password—are configured in the JNDI data source itself.

Finally, we come to the last bean in the helloworld-service.xml descriptor, one related to another important part to working with RDBMSs: transactions. The transactionManager bean is associated to the Spring-provided class org.springframework.orm.jpa.JpaTransactionManager, which is then charged with managing transactions on none other than the entityManagerFactory and dataSource beans, as can be seen by the respective <property> fields.

And last but not least, let's not forget the topmost declaration in the form, <tx:annotation-driven/>, which is used totell Spring to inspect declared beans for annotations related to transactions that in this case will enforce the transaction annotations specified in the DAO class.

With this, you now know the necessary descriptors for using JPA and Spring in the same application. For the moment, it's not important to know where these descriptor files need to be placed; in due time I will tell you where they should go.

Compiling the Domain Model

Before leaving your domain model POJOs decorated with JPA annotations and moving on to the next section, it's convenient to compile the classes not only to give this section closure, but also because the next section builds on compiled versions of these classes.

If you've been following along since Chapter 1, which presented a Hello World OSGi application and introduced the Hello World "playground," you may recall the compilation process for the book's applications rely on the use of Apache Ant.

Use the same Java Ant build.xml file presented back in Chapter 1—specifically Listing 1-6, which was used to compile classes—and place this chapter's classes according to their packages in the Hello World "playground" directory presented in Figure 2-1. Now follow these steps to enact the compilation process:

  1. Copy dependent JAR files to the lib directory: as the domain model classes rely on several third-party libraries, you need to copy each of the following JARs to the HelloWorld "playground" lib directory.

    • persistence.jar: Located in the lib/j2ee directory of the Spring Framework with dependencies download

    • spring-beans.jar: Located in the dist/modules directory of the Spring Framework with dependencies download

    • spring-core.jar: Located in the dist/modules directory of the Spring Framework with dependencies download

    • spring-orm.jar: Located in the dist/modules directory of the Spring Framework with dependencies download

    • spring-tx.jar: Located in the dist/modules directory of the Spring Framework with dependencies download

  2. Execute ant compile: while in the root directory of the Hello World "playground," execute the command ant compile. This will initiate the compilation process and place the compiled classes under the classes directory.

You've now finished creating and compiling your HelloWorld domain model. It's time to get some hands-on experience on another area touted from the outset in Spring: testing.

Testing Your Domain Model

Similar to the use of JPA in the last section, this exploration into the world of Java testing with Spring will be limited to a few basic constructs, since in much the same way, testing in itself is an extremely big subject, with numerous types and tools to support it in Java. That said, the two types of testing this Hello World application will demonstrate are unit testing and integration testing.

Unit Testing

Unit testing refers to process of guaranteeing the integrity of individual classes—hence the term "unit." It is the simplest form of software testing, because creating tests on individual classes is relatively easy.

Take for example your HelloWorld or Person class. Both contain numerous getter and setter methods, so creating a unit test for either class would consist of generating an object of each kind, invoking a series of setter and getter sequences, and later proving whether the outcome for the sequences turned out with the expected results. It's a classic process of "getting what you expect" from "what you put in": if you don't get the expected results, it means a class's logic is broken in some way.

In this Hello World application, things can't go terribly awry with the two classes in question, but in POJOs performing more elaborate logic, unit testing can avoid the presence of some pretty nasty behavioral errors that would be impossible to detect at compile time.

Listing 2-11 shows a unit test for both the HelloWorld and Person classes.

Example 2-11. Hello World Application Unit Test Using JUnit

package com.apress.springosgi.ch2.tests;

import java.util.Date;
import junit.framework.TestCase;

import com.apress.springosgi.ch2.hello.HelloWorld;
import com.apress.springosgi.ch2.hello.Person;

public class HelloWorldUnitTests extends TestCase {

    private Person    trans1, trans2;
    private HelloWorld     hw1, hw2;
    protected void setUp() throws Exception {

        trans1 = new Person("John","Smith",45.00);

        trans2 = new Person();
        trans2.setFirstName("Carlos");
        trans2.setLastName("Perez");
        trans2.setHourlyRate(40.00);

        hw1 = new HelloWorld("English","Hello World!",new Date(),trans1);
        hw2 = new HelloWorld();
        hw2.setLanguage("Spanish");
        hw2.setMessage("Hola Mundo!");
        hw2.setTransdate(new Date());
        hw2.setTranslator(trans2);
    }
    public void testPerson() throws java.text.ParseException  {
        assertEquals("John", trans1.getFirstName());
        assertEquals("Smith", trans1.getLastName());
        assertEquals(45.00, trans1.getHourlyRate());

        assertEquals("Carlos", trans2.getFirstName());
        assertEquals("Perez", trans2.getLastName());
        assertEquals(40.00, trans2.getHourlyRate());

    }
public void testHelloWorld() {
        assertEquals("English", hw1.getLanguage());
        assertEquals("Hello World!", hw1.getMessage());
        assertEquals(new Date(), hw1.getTransdate());
        assertEquals(trans1, hw1.getTranslator());

        assertEquals("Spanish", hw2.getLanguage());
        assertEquals("Hola Mundo!", hw2.getMessage());
        assertEquals(new Date(), hw2.getTransdate());
        assertEquals(trans2, hw2.getTranslator());
    }
}

The unit test in this last listing leverages the Java testing framework JUnit, which provides an excellent environment in which to perform such tests. First off, notice how the unit test class inherits its behavior fromthe TestCase class, which forms part of the JUnit framework.

The first method in the unit test is the setUp() method, which takes care of instantiating two Person objects and two HelloWorld objects, with each object being generated through different means—in one case through a class's overloaded constructor method, and in another using the class's default constructor and later using its corresponding setter methods.

An important aspect of the JUnit framework is that each of the objects generated in the setUp() method will be created at the outset of a test, further making these objects available to other methods in the unit test for future usage.

Continuing with the sequence of methods, you will find the testPerson() method, which is charged with testing the Person class. Inside this last method are various statements starting with assertEquals()—which is a JUnit method—used to invoke various getter methods on the Person objects created in setUp(), and comparing them to the expected values as inputted in this latter method. If for some reason the assertion fails, the unit test is said to have failed.

The testHelloWorld() method does pretty much the same as its testPerson() counterpart, except it does so for the HelloWorld class, identically using JUnit's assert() method to prove an object's getter methods return the expected values as inputted in the setUp() method.

This is basically the same process for performing any unit test usingthe JUnit framework, so you could easily add another testXXX() method to include more assert statements—or some other JUnit variation—to unit test any other class.

As far as the actual bootstrapping and execution of unit tests is concerned, JUnit offers various approaches, ranging from its own stand-alone GUI, to external support in IDEs like Eclipse, to the Java build utility you've already used and will be the tool of choice: Apache Ant. But before you get to executing unit tests, let's take a look at how you can perform integration testing on your Hello World application.

Integration Testing

Integration testing can be a little more elaborate than unit testing, since it consists of taking numerous parts—units—and testing how they interact with one another, with the addition of acquiring other resources and services to perform the necessary tests on the underlying logic.

In your Hello World application, you have a perfect candidate to perform integration testing on, the DAO class presented back in Listing 2-10. In this case, the integration test would consist of guaranteeing that each of the DAO's actions returned the appropriate results from an RDBMS.

This process is by far lengthier than the earlier unit test, since it entails prepopulating an RDBMS with values, performing a class's operations against an RDBMS, and verifying the output from the RDBMS is returned as expected. Fortunately, and as you will now see, Spring has excellent built-in support for bootstrapping resources like RDBMS for the purpose of testing. Listing 2-12 contains the integration test used for the HelloWorldService DAO class.

Example 2-12. Hello World Application Integration Test Using Spring

package com.apress.springosgi.ch2.tests;

import java.util.Date;
import java.util.List;

import com.apress.springosgi.ch2.hello.HelloWorld;
import com.apress.springosgi.ch2.hello.Person;
import com.apress.springosgi.ch2.hello.HelloWorldService;

import org.springframework.test.jpa.AbstractJpaTests;

public class HelloWorldServiceIntegrationTests extends AbstractJpaTests {

    private HelloWorldService helloWorldService;

    private long EnglishId;
    private long SpanishId;
    private long FrenchId;

    public void setHelloWorldService(HelloWorldService helloWorldService) {
        this.helloWorldService = helloWorldService;
    }
protected String[] getConfigLocations() {

        return new String[] { "classpath:/com/apress/springosgi/ch2/tests/
Hello World Application Integration Test Using Spring
helloworld-service.xml" };
} protected void onSetUpInTransaction() throws Exception { HelloWorld hw1 = new HelloWorld("English", "Hello World!", new Date(), new Person("John","Smith",45.00)); HelloWorld hw2 = new HelloWorld("Spanish", "Hola Mundo!", new Date(), new Person("Carlos","Perez",40.00)); HelloWorld hw3 = new HelloWorld("French", "Bonjour Monde!", new Date(), new Person("Pierre","LeClair",40.00)); helloWorldService.save(hw1); helloWorldService.save(hw2); helloWorldService.save(hw3); EnglishId = helloWorldService.findByLanguage("English").get(0).getId(); SpanishId = helloWorldService.findByLanguage("Spanish").get(0).getId(); FrenchId = helloWorldService.findByLanguage("French").get(0).getId(); } public void testFindById() { HelloWorld hw = helloWorldService.findById(EnglishId); assertNotNull(hw); assertEquals("English", hw.getLanguage()); } public void testFindByDoesNotExistId() { HelloWorld hw = helloWorldService.findById(10000); assertNull(hw); } public void testFindByLanguage() { List<HelloWorld> hws = helloWorldService.findByLanguage("Spanish"); assertEquals(1, hws.size()); HelloWorld hw = hws.get(0); assertEquals("Hola Mundo!", hw.getMessage()); }
public void testFindByBadLanguage() {
       List<HelloWorld> hws = helloWorldService.findByLanguage("Catalan");
       assertEquals(0, hws.size());
    }

    public void testFindByTranslatorFirstName() {
        List<HelloWorld> hws = helloWorldService.findByTranslatorFirstName("John");
        assertEquals(1, hws.size());
        HelloWorld hw = hws.get(0);
        assertEquals(EnglishId, hw.getId());
    }

    public void testFindByTranslatorLastName() {
        List<HelloWorld> hws = helloWorldService.findByTranslatorLastName
Hello World Application Integration Test Using Spring
("LeClair"); assertEquals(1, hws.size()); HelloWorld hw = hws.get(0); assertEquals(FrenchId, hw.getId()); } public void testFindByTranslatorFirstNameDoesNotExist() { List<HelloWorld> hws = helloWorldService.findByTranslatorFirstName("Bill"); assertEquals(0, hws.size()); } public void testFindByTranslatorLastNameDoesNotExist() { List<HelloWorld> hws = helloWorldService.findByTranslatorLastName
Hello World Application Integration Test Using Spring
("Matsusaka"); assertEquals(0, hws.size()); } public void testFindByTranslatorHourlyRateOver() { List<HelloWorld> hws = helloWorldService.findByTranslatorHourly
Hello World Application Integration Test Using Spring
RateOver(42.00); assertEquals(1, hws.size()); } public void testModifyHelloWorldMessage() { String oldHelloMessage = "Bonjour Monde!"; String newHelloMessage = "Bonjour Le Monde!"; HelloWorld hw = helloWorldService.findByLanguage("French").get(0); hw.setMessage(newHelloMessage);
HelloWorld hw2 = helloWorldService.update(hw);
        assertEquals(newHelloMessage, hw2.getMessage());

        List<HelloWorld> hw3 = helloWorldService.findByMessage(oldHelloMessage);
        assertEquals(0, hw3.size());

        hw3 = helloWorldService.findByMessage(newHelloMessage);
        assertEquals(1, hw3.size());
        HelloWorld newhw3 = hw3.get(0);
        assertEquals(newHelloMessage, newhw3.getMessage());
    }
 public void testDeleteHelloWorldCascade() {
        String transFirstName = "Carlos";
        HelloWorld hw = helloWorldService.findByTranslatorFirstName
Hello World Application Integration Test Using Spring
(transFirstName).get(0); int transCountBefore = countRowsInTable("person"); int helloCountBefore = countRowsInTable("helloworld"); helloWorldService.delete(hw); List<HelloWorld> hws = helloWorldService.findByTranslator
Hello World Application Integration Test Using Spring
FirstName(transFirstName); assertEquals(0, hws.size()); int transCountAfter = countRowsInTable("person"); int helloCountAfter = countRowsInTable("helloworld"); assertEquals(transCountBefore −1, transCountAfter); assertEquals(helloCountBefore −1, helloCountAfter); } public void testFindAll() { List<HelloWorld> hws = helloWorldService.findAll(); assertEquals(3, hws.size()); } }

Much like the DAO class itself, which relies on one of Spring's core classes to facilitate the use of JPA, this integration test class inherits it behavior from another Spring class named org.springframework.test.jpa.AbstractJpaTests.

As you will likely notice in the last listing, the layout in terms of methods and their names is strikingly similar to the earlier unit test. The first difference, though is the use of the setHelloWorldService() method, which injects an instance of HelloWorldService into the test. Next, you will find two methods that are executed at the outset of a test: getConfigLocations() and onSetUpInTransaction().

The getConfigLocations() method is used to locate the RDBMS's parameters against which the integration tests will be performed, with the assigned value being a Spring-JPA descriptor file like the one described in Listing 2-13 in the next section. On the other hand, the onSetUpInTransaction() is charged with creating and saving three HelloWorld objects—and their corresponding Person objects—to theRDBMS for further use by the class's testing methods.

The testing methods that start with the prefix testXXX() perform various operations against the RDBMS using the DAO methods, later leveraging methods like assertEquals() and countRowsInTable() to verify that the returned results are in line with the input objects created in the onSetUpInTransation() method.

Now let's take a brief sidestep and see what the RDBMS's parameters bootstrapped in the getConfigLocations() method look like.

JPA Descriptor Files for Integration Testing

Since integration testing is mostly performed on development workstations and tends to be limited to a one-time affair, you will be taking the simplest and shortest route possible to set-up an RDBMS: a data source managed by Spring and an in-memory RDBMS to avoid any extra configuration steps.

Listing 2-13 illustrates the helloworld-service.xml descriptor used for integration testing.

Example 2-13. helloworld-service.xml Used in JPA-Spring for Integration Testing

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/
helloworld-service.xml Used in JPA-Spring for Integration Testing
spring-beans.xsd"> <bean id="helloWorldService" class="com.apress.springosgi.ch2.hello.HelloWorldDAO"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </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.OpenJpaVendorAdapter">
               <property name="showSql" value="true"/>
               <property name="generateDdl" value="true"/>
               <property name="databasePlatform" value="org.apache.openjpa.jdbc.sql.
helloworld-service.xml Used in JPA-Spring for Integration Testing
HSQLDictionary"/>
</bean> </property> <property name="loadTimeWeaver"> <bean class="org.springframework.instrument.classloading.SimpleLoadTimeWeaver"/> </property> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.Driver
helloworld-service.xml Used in JPA-Spring for Integration Testing
ManagerDataSource"> <property name="driverClassName" value="org.hsqldb.jdbcDriver"/> <property name="url" value="jdbc:hsqldb:mem:springosgi"/> <property name="username" value="sa" /> <property name="password" value="" /> </bean> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransaction
helloworld-service.xml Used in JPA-Spring for Integration Testing
Manager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> <property name="dataSource" ref="dataSource"/> </bean> </beans>

The RDBMS parameters specified in this last descriptor belong to the HSQL database— databasePlatform = HSQLPlatform—a popular in-memory RDBMS with the same general behaviors as more heavyweight RDBMSs, while specifying that JPA generate logging information— showSQL=true—and that it attempt to generate and update relational tables each time the Entity Manager is initialized— generateDdl=true. Additional parameters also include those for the data source, which are the HSQLDB driver, connection URL, and the default username and password for HSQLDB.

It should also be noted that since HSQLDB is configured an in-memory solution, data never survives beyond the parent process that initiates it, though for the purpose of testing and since JPA uses generateDdl=true, this is a perfectly reasonable trade-off.

Besides the helloworld-service.xml descriptor shown here, the JPA also requires a default persistence.xml descriptor. Whether used in the context of testing or deploying production-type Spring JPA applications, this file never changes, and hence can be taken from the code presented in Listing 2-9 earlier.

With this you finish up all aspects related to integration testing on your Hello World Spring application; now it's time to execute this test along with the corresponding unit test created earlier.

Running Tests

For executing the Hello World application tests, you will once again rely on the Apache Ant build tool. Prior to defining this Ant task, though, make sure you have incorporated all the following steps into your Hello World "playground":

  1. Copy the test classes to the appropriate directory: ensure the sources for both the unit and integration tests are placed according to their package in the subdirectory src/com/apress/springosgi/ch2/tests/.

  2. Copy the Spring-JPA descriptor to the appropriate directory: make sure the helloworld-service.xml descriptor in Listing 2-13 is also located under the subdirectory src/com/apress/springosgi/ch2/tests/.

  3. Copy the JPA default descriptor to the appropriate directory: a copy of the persistence.xml file from Listing 2-9should be placed under the subdirectory src/META-INF/ch2/.

  4. Copy dependent JAR files to the lib directory: the test classes incorporate new dependencies into the application. Copy each of the following JARs to the Hello World "playground" lib directory:

    • commons-logging.jar: Located in the lib/jakarta-commons directory of the Spring Framework with dependencies download

    • commons-lang.jar: Located in the lib/jakarta-commons directory of the Spring Framework with dependencies download

    • commons-collections.jar: Located in the lib/jakarta-commons directory of the Spring Framework with dependencies download

    • hsqldb.jar: Located in the lib/hsqldb directory of the Spring Framework with dependencies download

    • junit.jar: Located in the lib/junit directory of the Spring Framework with dependencies download

    • jta.jar: Located in the lib/j2ee directory of the Spring Framework with dependencies download

    • serp.jar: Located in the lib/serp directory of the Spring Framework with dependencies download

    • spring.jar: Located in the dist directory of the Spring Framework with dependencies download

    • spring-test.jar: Located in the dist/modules directory of the Spring Framework with dependencies download

    • openjpa.jar: Located in the lib/openjpa directory of the Spring Framework with dependencies download

  5. Copy junit.jar to Apache Ant's lib directory: ensure the junit.jar file—located in the lib/junit directory of the Spring Framework with dependencies download—is copied over to Apache Ant's lib directory.

With all dependencies, classes, and descriptor files in place, define an Ant task for the purpose of performing the application's unit and integration tests. Listing 2-14 shows such a task.

Example 2-14. Ant Task for Performing Unit and Integration Tests

<target name="ch2" depends="compile" description="Build Chapter 2 
Ant Task for Performing Unit and Integration Tests
Spring Application"> <echo message="-------------- Building Chapter 2 Spring Application for
Ant Task for Performing Unit and Integration Tests
Pro Spring-OSGi -------------- "/> <property name="ch2.dir" value="${dist.dir}/ch2/"/> <mkdir dir="${ch2.dir}"/> <property name="test.dir" value="${ch2.dir}/tests"/> <mkdir dir="${test.dir}"/> <mkdir dir="${ch2.dir}/lib/"/> <mkdir dir="${build.dir}/META-INF"/> <copy file="${src.dir}/META-INF/ch2/persistence.xml" tofile=
Ant Task for Performing Unit and Integration Tests
"${build.dir}/META-INF/persistence.xml"/> <junit printsummary="yes"> <classpath refid="classpath"/> <formatter type="brief"/>
      <batchtest todir="${test.dir}">
         <fileset dir="${build.dir}">
           <include name="com/apress/springosgi/ch2/tests/*"/>
         </fileset>
      </batchtest>
  </junit>

</target>

This Ant task starts off by declaring a dependency on the compile target, ensuring that prior to attempting any tests, all classes are properly compiled. It then sets off on a few housekeeping tasks, creating a ch2 and test build directory to output results, and copying the persistence.xml descriptor over to the project's build directory, so it can be picked up by Java's classpath as required by the integration test.

Then you can observe the <junit> task, which in itself contains the printsummary="yes" attribute used for outputting one-line statistics on each test. Nested inside <junit>, you will also find numerous declarations used for the following:

  • <classpath>: Indicates the Ant variable to use as the Java CLASSPATH for executing tests, in this case containing a value pointing to the lib and compiled class directories.

  • <formatter>: Specifies the type of formatting to use for the results obtained on each test.

  • <batchtest>:Defines the location in which to place testing reports, as well as where to locate the classes containing the tests via a <fileset> directive. In this case, notice that the <fileset> directive points toward the com/apress/springosgi/ch2/tests/ subdirectory, which is where the compiled tests classes are placed.

Now, while inside the root directory of the Hello World "playground," invoke ant ch2. This last instruction will trigger the tests, presenting a one-line summary of the results on the console, and if you go to the dist/ch2/test subdirectory, you will be able to consult a detailed report on every test, including error stacks for failed tests and SQL logging information for integration tests, among other things.

You now have a tested domain model connecting to an RDBMS via JPA, but still no graphical interface for showing off such logic. It's time to switch gears over to another application tier in which Spring can also aid you with its POJO approach: the web tier.

Using Spring's MVC

Java web development often goes hand in hand with the MVC pattern, an approach that supports the multitier and stateless nature of web-enabled applications. Nowadays, nearly all Java web frameworks make use of the MVC pattern to a greater or lesser extent, and in Spring's case, it offers its own brew designed to accommodate the same IoC nature you saw in the domain model.

To integrate the MVC pattern in the Hello World Spring application, you already have your work cut out for you, since what you did in the last section as your domain model is the equivalent to the "Model" in MVC. The next thing you have to do is create a controller that will be charged with hooking up the model with the different views in the system.

Creating a Spring Controller

A Spring controller in the context of the MVC pattern takes care of brokering all incoming requests made to a web application, performing any corresponding action requested by the originating party—creating, reading, updating, or deleting data—and later delegating each request to an appropriate view indicating the outcome.

Listing 2-15 contains the controller used for the Hello World application.

Example 2-15. HelloWorldController.java

package com.apress.springosgi.ch2.mvc;

import java.util.List;
import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.ui.ModelMap;

import com.apress.springosgi.ch2.hello.HelloWorld;
import com.apress.springosgi.ch2.hello.Person;
import com.apress.springosgi.ch2.hello.HelloWorldService;

@Controller
public class HelloWorldController {

    private HelloWorldService helloWorldService;
@Autowired
    public HelloWorldController(HelloWorldService helloWorldService) {
        this.helloWorldService = helloWorldService;
    }

    @RequestMapping(method = RequestMethod.GET)
    @ModelAttribute("helloworlds")
    public List<HelloWorld> home() {
        return this.helloWorldService.findAll();
    }

    @RequestMapping(method = RequestMethod.GET)
    public String translator(@RequestParam("id") Long id, ModelMap model) {
     Person translator = helloWorldService.findById(id).getTranslator();
     List<HelloWorld> hws = helloWorldService.findAll();
     model.addAttribute("helloworlds",hws);
     model.addAttribute("translator",translator);
     return "home";
    }

    @RequestMapping(method = RequestMethod.GET)
    public String deleteMessage(@RequestParam("id")
    Long id) {
        helloWorldService.deleteMessage(id);
        return "redirect:home";
    }
}

The first thing that will likely strike you about this listing is its ample use of annotations, which are Spring controller annotations. Let's break down what each of them means.

At the top of the listing you will see that the class is designated with a @Controller annotation, which is simply indicating the class will be used for this purpose. Moving along, you will encounter the @Autowired annotation on the class's constructor method, which indicates it will be auto-wired with Spring's dependency injection facilities. What this means is that the controller will gain access to whatever beans are declared inside its constructor, in this case a HelloWorldService bean and all its corresponding methods that have access to an RDBMS.

Next, you will find three methods decorated with the @RequestMapping annotation. The @RequestMapping annotation dictates on what incoming request a method's actions will be executed; in this case, the value (method = RequestMethod.GET) is an open-ended way to inspect all incoming requests and match them against a method's name.

For example, if this controller handled a request in the form http://localhost/home, this would trigger the actions of the home() method; similarly, a request for http://localhost/translator?id=2 would execute the logic in the translator() method, and so on.

In a similar manner, if a request came into this controller and no corresponding method by that name was found—for example, http://localhost/foobar—no action would taken. Alternatively, @RequestMapping can also take a hard-coded value in case an incoming request requires it to match long or different method names (e.g., the annotation @RequestMapping(" /zipcode") decorating the method searchInAVeryLongNameMethodForZipcodes() would result in the method being executed on a request to the URL http://localhost/zipcode).

While the @RequestMapping annotation manages incoming requests, the @ModelAttribute annotation defines how the data for each method is transferred over to a corresponding view. For example, in the topmost controller method, home(), the value @ModelAttribute("helloworlds") indicates that whatever values are returned by the method in question will be placed inside a variable by the name helloworlds to later be manipulated inside a view template.

The remaining two methods make use of the find @RequestParam annotation, which extracts a parameter from the incoming request URL and passes it as an input value to a controller method. Of noted importance is that these same two methods don't make use of the @ModelAttribute annotation. So does this mean they don't return data to a view template? No, they still do, they just do it differently.

The second method makes use of a ModelMap object, which assigns two objects obtained from DAO service calls, information that will later be made available to a view template through the helloworld and translator values. In this scenario, the return value for the method indicates the name of the view to which control will be rescinded.

Before we move to the last method in the controller, you may be wondering what view name the first method returns control to, being it returns data. That would be to a method's default view, the one with the same name as the method, so the home() method would relinquish control over to a view named home, the same view explicitly returned in the second method.

Finally, we come to the third method in the controller, which eliminates a record from the RDBMS. This method rescinds control using the string redirect:home, signifying that the request be redirected to the home() method for further processing, further executing this last method's logic—obtaining all the messages in the RDBMS—and making them available to the home view. The logic behind this last controller method will become more obvious once you see its use in fulfilling AJAX type requests.

All the views—or the home view in this application—designated by Spring controllers are said to be logical views; in other words, they are not a physical view template (a file by that name) but are rather further mapped to one of the many view technologies supported by Spring's MVC, which include JavaServer Pages (JSP), JSP Standard Tag Library (JSTL), JavaServer Faces (JSF), and Apache Tiles, among others.

So let's see how a logical view in a Spring controller gets mapped to a view technology.

Creating Views with Tiles

In the context of Spring's MVC, a view can consist of everything from a vanilla HTML page, to an XML document, run-of-the mill JSP, or JSF, to a more sophisticated view system like Apache Tiles.

For your Hello World application, you will be using Apache Tiles, a comprehensive templating system that allows a web page to be divided into different units, permitting each unit to have its own structure made of either JSTL tags, JSP code, or simple text.

Its design is tailor-made to providing solutions for many of the layout issues faced in web applications, like avoiding monolithic pages and instead dividing a layout in terms of header, footer, sidebars, and body templates. Additionally, Apache Tiles integrates nicely with Spring's Web Flow project, a front-end companion to Spring's MVCs that supports complex page navigations and also includes the necessary libraries to use AJAX in Spring, and which will also be touched upon in this application.

Now that you know why I opted to have you use Apache Tiles as the view technology, take a look at Listing 2-16, which contains the main definition file for the tiles used in the Hello World application.

Example 2-16. Apache Tiles Definition File— tiles.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
 <!DOCTYPE tiles-definitions PUBLIC
       "-//Apache Software Foundation//DTD Tiles Configuration 2-0//EN"
       "http://tiles.apache.org/dtds/tiles-config_2_0.dtd">
<tiles-definitions>

  <definition name="home" template="/jsp/home.jsp">
      <put-attribute name="title" value="Hello World - Pro Spring-OSGi"/>
      <put-attribute name="header" value="/jsp/tiles/header.jsp"/>
      <put-attribute name="content" value="index.body"/>
      <put-attribute name="footer" value="/jsp/tiles/footer.jsp" />
  </definition>

  <definition name="index.body" template="/jsp/tiles/body.jsp">
      <put-attribute name="helloMessages" value="/jsp/tiles/messages.jsp" />
      <put-attribute name="helloTranslators" value="/jsp/tiles/translators.jsp" />
      <put-attribute name="translator" value="/jsp/tiles/translator.jsp" />
  </definition>

</tiles-definitions>

The main page layout is contained in the <definition> named home, which points to a template named /jsp/home.jsp. Notice though that nested inside the home <definition> element are numerous <put-attribute> values, each of which represents a tile for the template.

One of these <put-attribute> elements declares a String value, while two others point to different JSP code, and yet another points to index.body, which is a <definition> statement also defined in the file. Listing 2-17 shows what the main Apache Tiles template, /jsp/home.jsp (which is assigned to the home <definition>), looks like.

Example 2-17. Home Page home.jsp) Using Apache Tiles

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
        "http://www.w3.org/TR/html4/strict.dtd">
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>

         <title><tiles:getAsString name="title"/></title>
        <link href="/springhelloworld/css/hello.css" rel="stylesheet"
Home Page home.jsp) Using Apache Tiles
type="text/css"> <script type="text/javascript" src="<c:url value="/resources/dojo/
Home Page home.jsp) Using Apache Tiles
dojo.js" />"> </script> <script type="text/javascript" src="<c:url value="/resources/spring/
Home Page home.jsp) Using Apache Tiles
Spring.js" />"> </script> <script type="text/javascript" src="<c:url value="/resources/spring/
Home Page home.jsp) Using Apache Tiles
Spring-Dojo.js" />"> </script> </head> <body> <div id="wrap"> <div id="header"> <h1><tiles:insertAttribute name="header"/></h1> </div> <div id="content"> <tiles:insertAttribute name="content"/> </div> <div id="footer"> <h3><tiles:insertAttribute name="footer"/></h3> </div> </div> </body> </html>

Notice how this template has numerous <tiles:insertAttribute> elements scattered with plain HTML, and that each of these values corresponds to a <put-attribute>name as declared in the Apache Tiles definition file.

What Apache Tiles will do upon rendering this particular template is replace each of these values with those declared in the definition file, so <tiles:getAsString name="title"/> will be replaced by the string 'Hello World - Pro Spring-OSGi',<tiles:insertAttribute name="header"/> with the contents of the file /jsp/tiles/header.jsp, and so on.

It's a powerful layout approach, and one that can be nested to numerous degrees as can be observed in the content tile value, which points to another template that itself is composed of even more tiles.

Shifting the focus back to the controller designed earlier, recall that it was precisely the controller that is required to send control back to a logical view named home. As it turns out, each of the <definition> names in an Apache Tiles definition file maps to a logical view; this means that when a request comes into http://localhost/home, the logic inside the controller method home() will executed, returning a rendered Apache Tiles home view with all its nested tiles back to an end user.

Also remember the controller home() method returns a set of data extracted from the RDBMS that would be made available under the helloworlds name, so where is this information? This data is being manipulated in a tile within a tile, the helloMessages tile pointing to the jsp/tiles/messages.jsp file, which of course still forms part of the logical home view, nested as it may be. Listing 2-18 shows what the helloMessages tile's underlying JSP looks like and how it processes data sent by the controller.

Example 2-18. HelloMessage Tile messages.jsp) Processing Controller Data with AJAX Calls

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
 <div id="helloMessages">
 <c:forEach var="hello" items="${helloworlds}">
   <div style="border:red 2px dashed;margin:10px;padding:5px">
       <b><c:out value="${hello.language}"/></b>
       <c:out value="${hello.message}"/> - Translated on:     <fmt:formatDate
HelloMessage Tile messages.jsp) Processing Controller Data with AJAX Calls
value="${hello.transdate}" dateStyle="long" /> <br/> <a id="deleteMessage_${hello.id}" href="deleteMessage?id=${hello.id}">
HelloMessage Tile messages.jsp) Processing Controller Data with AJAX Calls
Delete Message </a>
<script type="text/javascript"> Spring.addDecoration(new Spring.AjaxEventDecoration({ elementId:"deleteMessage_${hello.id}", event:"onclick", params: {fragments:"helloMessages,helloTranslators"} }));
       </script>
       <br/>

   </div>
 </c:forEach>
</div>

The JSP for this last tile makes use of the JSTL core library for iterating over the helloworlds data set sent by the controller and lays out each message inside an HTML <div> element. This tile has another important aspect of the Hello World application: an AJAX call.

In case you are unfamiliar with the term "AJAX," what this technique allows a web application to do is perform an out-of-band call from a browser back to a server-side controller, without the user experiencing a complete page refresh; in essence, only a piece of a page is updated.

The AJAX call in this tile is brought to you by the HTML link <a id="deleteMessage_${hello.id}" href="deleteMessage?id=${hello.id}">Delete Message </a>, which effectively calls deleteMessage?id=${hello.id}, invoking the deleteMessage() controller method, which in turn eliminates the message from the RDBMS.

This last HTML link doesn't act like a standard HTML link on account of the JavaScript declaration right next to it, the one starting with a JavaScript method Spring.addDecoration() that has the nested Spring.AjaxEventDecoration() method, which includes the following definitions:

  • elementId: This parameter associates a given HTML ID to an AJAX event. In this case, the value deleteMessage_${hello.id} signifies that each of the corresponding links (<a>) to delete a message will be associated with an AJAX call, hence overriding the default behavior of links to navigate to a new page.

  • event: This parameter indicates on what action the AJAX event will be triggered. In this case, an onclick event on the given elementId will trigger the AJAX call.

  • params: This parameter indicates what tile and HTML ID to re-render once the AJAX call has completed. In this case, since you are eliminating messages, params is indicating that both the helloMessages and helloTranslators tiles and HTML IDs—which contain messages—will be re-rendered, with the remaining tiles in the page remaining without update.

All this AJAX functionality comes from Spring's JavaScript module, which forms part of the grander Spring Web Flow project, the latter of which is a companion to projects made around Spring's MVC module. Here, the actual JavaScript libraries are made available through declarations at the top of the main template in Listing 2-17.

The remaining tiles composing the home page view contain another similar AJAX call and a few more basic constructs made up of text, HTML, and JSTL. Listings 2-19 through 2-25 show the application's remaining tiles, main index, and CSS file.

Example 2-19. Header Tile (header.jsp) for Hello World

Spring Application - Pro Spring-OSGi

Example 2-20. Footer Tile footer.jsp) for Hello World

Pro Spring OSGi by Daniel Rubio - Published by Apress

Example 2-21. Body Tile body.jsp) for Hello World

<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
       <div id="index.body">
          <div id="main">
                  <h2>Hello World Messages </h2>
                  <tiles:insertAttribute name="helloMessages"/>
          </div>
          <div id="sidebar">
              <h2>Translators </h2>
                 <tiles:insertAttribute name="helloTranslators"/>

                 <tiles:insertAttribute name="translator"/>
          </div>
    </div>

Example 2-22. HelloTranslators Tile (translators.jsp) for Hello World

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<div id="helloTranslators">
 <ul>
  <c:forEach var="hello" items="${helloworlds}">
       <li><c:out value="${hello.language}"/>
       <a id="showTranslator_${hello.id}" href="translator?id=${hello.id}">
HelloTranslators Tile (translators.jsp) for Hello World
Translator Details </a> <script type="text/javascript"> Spring.addDecoration(new Spring.AjaxEventDecoration({ elementId:"showTranslator_${hello.id}", event:"onclick", params: {fragments:"translator"} })); </script></li>
</c:forEach>
 </ul>
</div>

Example 2-23. Translator Tile (translator.jsp) for Hello World

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  <div id="person">
  <div style="border:red 2px dashed;margin:10px;padding:5px;">
   <b>Name</b> :<c:out value="${translator.firstName}"/>
Translator Tile (translator.jsp) for Hello World
<c:out value="${translator.lastName}"/><br/> <b>Hourly Rate</b> : $<c:out value="${translator.hourlyRate}"/><br/> </div> </div>

Example 2-24. Main Index (index.html) for Hello World

<html>
<head>
  <meta http-equiv="Refresh" content="0; URL=spring/home">
</head>
</html>

Example 2-25. Cascading Style Sheet (hello.css) for Hello World

body,
html {
        margin:0;
         padding:0;
         background:#a7a09a;
        color:#000;
}

body {
        min-width:750px;
}

#wrap {
         background:#ffffff;
        margin:0 auto;
        width:750px;
}
#header {
         background:#cfcfcf;
}

#header h1 {
         padding:5px;
         margin:0;
         text-align:center;
}
#main {
         background:#dfdfdf;
         float:left;
         width:500px;
}

#main h2, #main h3, #main p {
        padding:0 10px;
}

#sidebar {
         background:#ffffff;
         float:right;
         width:240px;
}

#sidebar ul {
        margin-bottom:0;
}

#sidebar h3, #sidebar p {
         padding:0 10px 0 0;
}
#footer {
         background:#bfbfbf;
         clear:both;
         text-align:center;
}

#footer p {
         padding:5px;
         margin:0;
}.

Copy the following files to the specified directories in the Hello World "playground": the main index.html file in Listing 2-24 to the src/GUI/ch2/ directory, the hello.css file in Listing 2-25 to the src/GUI/ch2/css/ directory, and the home.jsp file in Listing 2-17 to the src/GUI/ch2/jsp/ directory. You will also need to copy all tiles in Listings 2-18 through 2-23 to the directory src/GUI/ch2/jsp/tiles/.

Up next, you will create the corresponding descriptors needed to accompany the controller class, Apache Tiles definition file, and Apache Tiles templates you just created.

Spring MVC Descriptors

A Spring MVC project is always accompanied by the de facto descriptor used in Java web applications and a few other descriptors containing Spring's MVC behaviors. Listing 2-26 contains the web.xml file that is always used in Java web applications, applied to the Hello World application.

Example 2-26. web.xml for the Hello World Spring Application

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
web.xml for the Hello World Spring Application
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schema
web.xml for the Hello World Spring Application
Location="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/
web.xml for the Hello World Spring Application
j2ee/web-app_2_4.xsd"> <display-name>Pro Sprng-OSGi</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/helloworld-service.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <servlet> <description> Pro Spring-OSGi MVC Dispatch Servlet </description> <display-name>DispatcherServlet</display-name> <servlet-name>helloworld</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet>
<servlet>
            <servlet-name>ResourcesServlet</servlet-name>
           <servlet-class>org.springframework.js.resource.ResourceServlet
web.xml for the Hello World Spring Application
</servlet-class> </servlet> <servlet-mapping> <servlet-name>helloworld</servlet-name> <url-pattern>/spring/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ResourcesServlet</servlet-name> <url-pattern>/resources/*</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> <resource-ref> <description>Database Connection</description> <res-ref-name>jdbc/springosgi</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> </web-app>

The web.xml descriptor starts off by associating the helloworld-service.xml descriptor—which contains the DAO, JPA, and RDBMS properties—with the application's context through Spring's ContextLoaderListener class. Back when you tested your domain model, you also made use of a helloworld-service.xml file to associate the DAO class with a JPA Entity Manager and its corresponding data source. This time around though, the file will be different.

Since the application will now be deployed on the Web, it requires a more robust approach. Listing 2-27 contains the helloworld-service.xml descriptor needed to use MySQL as the underlying RDBMS and leverage an externally administered data source through JNDI.

Continuing with the web.xml file, you will find the declaration for two servlets, one of the type DispatcherServlet and another of the type ResourceServlet. The former is part of Spring's MVC module and the latter part of Spring's Web Flow/JavaScript module, with Spring's dispatcher servlet providing the "plumbing" for most web controller actions and Spring's resource servlet providing prepackaged resources—JavaScript libraries—for actions related to AJAX.

Next are the corresponding servlet mapping declarations, indicating under what URLs the servlets in question will be executed. Spring's dispatcher servlet will be invoked on every request under the spring directory, and Spring's resource servlet will also make use of the same wildcard notation except under the resources directory.

Finally, observe the <welcome-file-list> and <welcome-file> parameters used to configure a default home page for an application, as well as a <resource-ref> declaration loading a JNDI data source named jdbc/springosgi provided by an application server/container.

As this last data source is inside web.xml, it has some further configuration issues you need to address: how to go about its configuration in an application server/container—which you will explore in the upcoming section—and how to associate the data source to its corresponding JPA Entity Manager and the DAO classes it will manage. Listing 2-27 contains the helloworld-service.xml used for this purpose, which is similar in nature to the one employed in the testing phase of the domain model.

Example 2-27. helloworld-service.xml Used in JPA-Spring for Production Deployment

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/
helloworld-service.xml Used in JPA-Spring for Production Deployment
spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/
helloworld-service.xml Used in JPA-Spring for Production Deployment
spring-tx-2.5.xsd"> <tx:annotation-driven/> <bean id="helloWorldService" class="com.apress.springosgi.ch2.hello.HelloWorldDAO"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </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.OpenJpaVendorAdapter">
               <property name="showSql" value="true"/>
               <property name="generateDdl" value="false"/>
               <property name="databasePlatform" value="org.apache.openjpa.jdbc.
helloworld-service.xml Used in JPA-Spring for Production Deployment
sql.MySQLDictionary"/> </bean> </property> <property name="loadTimeWeaver"> <bean class="org.springframework.instrument.classloading.SimpleLoadTimeWeaver"/> </property> </bean> <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="java:comp/env/jdbc/springosgi"/> </bean> <bean id="transactionManager" class="org.springframework.orm.jpa.Jpa
helloworld-service.xml Used in JPA-Spring for Production Deployment
TransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> <property name="dataSource" ref="dataSource"/> </bean> </beans>

In this Spring configuration used to wire up the DAO class with a data source and JPA Entity Manager, three things have changed from the configuration file you created for testing purposes.

One is the value generateDdl is set to false; this is done because it's not good practice for a JPA Entity Manager used in a production database to constantly refresh an RDBMS table's structure—DDL—each time it's started and stopped, which would equal each time the application itself is started and stopped.

And the other two changes correspond to the JPA data source, since the value databasePlatform is now pointing toward a mapping for a MySQL RDBMS, and the datasource bean is pointing toward an externally managed JNDI data source by an application server/container.

Next, you need to create just one more configuration file pertaining to the Spring Dispatcher servlet declared in web.xml. By convention, Spring looks for a Dispatcher servlet configuration file prefixed with its name. So in this case, since the Dispatcher servlet in web.xml is named helloworld, Spring will look for a configuration file named helloworld-servlet.xml. Listing 2-28 illustrates the helloworld-servlet.xml configuration file.

Example 2-28. helloworld-servlet.xml Used for Dispatcher Servlet

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/ 
helloworld-servlet.xml Used for Dispatcher Servlet
spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/
helloworld-servlet.xml Used for Dispatcher Servlet
spring-context-2.5.xsd"> <context:component-scan base-package="com.apress.springosgi.ch2.mvc"/> <bean id="urlMapper" class="org.springframework.web.servlet.handler.SimpleUrl
helloworld-servlet.xml Used for Dispatcher Servlet
HandlerMapping"> <property name="mappings"> <props> <prop key="/**">helloWorldController</prop> </props> </property> </bean> <bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer"> <property name="definitions"> <list> <value>/WEB-INF/tiles.xml</value> </list> </property> </bean> <bean id="tilesViewResolver" class="org.springframework.js.ajax.AjaxUrlBasedView
helloworld-servlet.xml Used for Dispatcher Servlet
Resolver"> <property name="viewClass" value="org.springframework.webflow.mvc.view.Flow
helloworld-servlet.xml Used for Dispatcher Servlet
AjaxTilesView"></property> </bean> </beans>

<context:component-scan>, which is the first declaration in the Dispatcher servlet file, is used to inspect class packages for annotations. In this case, the scan will be performed on the om.apress.springosgi.ch2.mvc package, which corresponds to the same package under which the MVC controller is located. This process will incorporate all the mappings and behaviors declared through annotations in the last class, as well as generate a Spring bean by the same name.

As you probably expected from seeing other Spring file configurations, next come various beans. The first bean declaration— urlMapper—is used to further map to the URL control that will be delegated. Given that you have only one controller class, the mapping for this Dispatcher servlet uses a wildcard to indicate that every request will be sent to the helloWorldController bean. Note that helloWorldController refers to a bean name, which is automatically available on account of the annotations used in this class and the previous component-scan declaration.

In the second bean declaration you will notice the Dispatcher servlet hooks up to the Apache Tiles logical views declared in Listing 2-16, effectively allowing the previous controller bean to redirect control to the appropriate logical tile names.

The third and last bean is a special bean provided by Spring's Web Flow project, allowing Apache Tiles to support AJAX calls to individual units. Under normal circumstances, an Apache Tiles definition file is considered to have logical names corresponding to top-level <definition> names only; as a consequence, without this definition your application would only have two logical names— home and index.body.

However, if you look back at the AJAX call described in the earlier tile (Listing 2-18), you will note that it makes use of refreshing certain internal tiles. It's with the AjaxUrlBasedViewResolver bean that each of the tile's <put-attribute> names are also converted into logical names, allowing control to be relinquished to individual tiles that provide AJAX type updates.

This concludes the review of all the parts that make up an MVC design in Spring. Up next, you will start ordering all these pieces to set the stage for final deployment.

Compiling and Preparing MVC Classes and Descriptors

Here is a list of steps you need to take from within the HelloWorld "playground" in order to compile and prepare all the MVC classes and descriptors you made in the last section.

  1. Copy the MVC controller to the appropriate directory: ensure the source for the controller class is placed in its package subdirectory src/com/apress/springosgi/ch2/mvc/.

  2. Copy all descriptor files to the appropriate directory: all descriptor files— helloworld-service.xml, helloworld-servlet.xml, tiles.xml, and web.xml—should be placed under the subdirectory src/WEB-INF/ch2/ of your Hello World "playground."

  3. Copy all view templates to the appropriate directory: all JSP, CSS, and HTML files related to Apache Tiles should be placed inside the subdirectory src/GUI/ch2/ and its corresponding subdirectories.

  4. Copy the dependent JAR file to the lib directory: the MVC controller class incorporates a new dependency into the application. Copy the spring-webmvc.jar JAR located in Spring's dist/modules download to the lib directory of the Hello World "playground."

As soon as you've followed through with these steps, you can take the next step, packaging everything in the format that is used to distribute Java web applications: WAR (Web Archive).

Creating the Web Archive

WAR is the standard packaging format used in Java web applications. Its importance is due to the fact that all Java application server/containers are designed to execute this type of file.

This makes WAR files a common distribution format for Java web applications in general—not only those designed around Spring—allowing this type of package to be equally deployed in the various Java application servers/containers available in the market. However, for your Hello World application, you will be relying on the Apache Tomcat container.

Although a WAR file needs to adhere to a certain structure in order to be deployed, at its core, it is nothing more than a unit containing Java classes, JAR libraries, deployment descriptors, and GUI templates like JSP or CSS files—which is practically all you've created since starting the Hello World application.

At this juncture you have all that's required to create a WAR file, except one piece: a descriptor needed to tell the application server/container how to set up a JNDI data source required by Spring's MVC model. Listing 2-29illustrates the context.xml descriptor file used specifically for setting up a JNDI data source on the Apache Tomcat container.

Example 2-29. context.xml Used for Configuring a JNDI Data Source

<Context>
<Loader loaderClass="org.springframework.instrument.classloading.tomcat.Tomcat
context.xml Used for Configuring a JNDI Data Source
InstrumentableClassLoader" useSystemClassLoaderAsParent="false"/> <Resource name="jdbc/springosgi" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="hello" password="world" driverClassName="com.mysql.
context.xml Used for Configuring a JNDI Data Source
jdbc.Driver" url="jdbc:mysql://127.0.0.1:3306/springosgi"/> </Context>

The listing starts off by declaring the use of the class TomcatInstrumentableClassLoader in the <Loader> element, a class that overrides Apache Tomcat's default class loader and enables weaving, with the attribute useSystemClassLoaderAsParent set to false in order to not lose Apache Tomcat's remaining loading of staple libraries.

The context.xml file then defines the actual data source through the <Resource> element, using a JNDI name in line with the one used in Spring's descriptor— jdbc/springosgi—and then indicating all the necessary connection credentials to access an RDBMS, which correspond to default MySQL values or those created when you installed MySQL.

Armed with this descriptor file, you now need to place it accordingly in the Hello World "playground," along with a few more JAR files needed by the application at runtime. The steps are as follows:

  1. Copy the context.xml descriptor: place a copy of the context.xml descriptor under the subdirectory src/META-INF/ch2/.

  2. Copy dependent JAR files to the lib directory: the WAR file, being a deployable unit, incorporates new runtime dependencies on the application. Copy each of the following JARs to the Hello World "playground" lib directory:

    • spring-web.jar: Located in the dist/modules directory of the Spring Framework with dependencies download

    • spring-context.jar: Located in the dist/modules directory of the Spring Framework with dependencies download

    • spring-jdbc.jar: Located in the dist/modules directory of the Spring Framework with dependencies download

    • jstl.jar: Located in the lib/j2ee directory of the Spring Framework with dependencies download

    • standard.jar: Located in the lib/jakarta-taglibs directory of the Spring Framework with dependencies download

    • aopalliance.jar: Located in the lib/aopalliance directory of the Spring Framework with dependencies download

    • spring-aop.jar: Located in the dist/modules directory of the Spring Framework with dependencies download

    • springframework.webflow.jar: Located in the dist directory of the Spring Web Flow download

    • springframework.js.jar: Located in the dist directory of the Spring Web Flow download

    • tiles-*.jar: All three located in the / (Root) directory of the Apache Tiles download

    • commons-*.jar: All three located in the lib directory of the Apache Tiles download

With every single file in place to create a WAR file, it's time to make use of Apache Ant in order to create it. Listing 2-30 contains the corresponding Ant syntax needed for the process.

Example 2-30. Ant Task for Building the JAR and WAR Files

<jar destfile="${ch2.dir}/lib/helloworld.jar">
    <fileset     dir="${build.dir}">
    <include name="com/apress/springosgi/ch2/hello/*"/>
   <include name="com/apress/springosgi/ch2/mvc/*"/>
    <include name="META-INF/persistence.xml"/>
  </fileset>
</jar>

<war destfile="${ch2.dir}/springhelloworld.war" webxml="${src.dir}/WEB-INF/ch2/
Ant Task for Building the JAR and WAR Files
web.xml"> <lib dir="${ch2.dir}/lib/"> <include name="helloworld.jar"/> </lib> <lib dir="${lib.dir}"> <include name="spring-core.jar"/> <include name="spring-beans.jar"/> <include name="spring-context.jar"/> <include name="spring-jdbc.jar"/> <include name="spring-orm.jar"/> <include name="spring-tx.jar"/> <include name="persistence.jar"/> <include name="jstl.jar"/> <include name="spring-web.jar"/> <include name="spring-webmvc.jar"/> <include name="standard.jar"/> <include name="persistence.jar"/> <include name="openjpa-1.0.2.jar"/> <include name="jta.jar"/> <include name="commons-collections.jar"/> <include name="commons-lang.jar"/>
<include name="serp-1.13.1.jar"/>
              <include name="aopalliance.jar"/>
              <include name="spring-aop.jar"/>
              <include name="org.springframework.js-2.0.2.RELEASE.jar"/>
              <include name="org.springframework.webflow-2.0.2.RELEASE.jar"/>
              <include name="tiles-api-2.0.6.jar"/>
              <include name="tiles-core-2.0.6.jar"/>
              <include name="tiles-jsp-2.0.6.jar"/>
              <include name="commons-beanutils-1.7.0.jar"/>
              <include name="commons-digester-1.8.jar"/>
              <include name="commons-logging-api-1.1.jar"/>
            </lib>
            <webinf dir="${src.dir}/WEB-INF/ch2/"/>
            <metainf dir="${src.dir}/META-INF/ch2/"/>
            <zipfileset dir="${src.dir}/GUI/ch2/" prefix=""/>
         </war>

The first declaration in the listing is used to create a JAR file needed by the WAR. What this JAR file will package are all the individual classes needed by the application, including the persistence.xml descriptor required by the JPA.

Next is the <war> task, which includes two attributes, a destfile value indicating where to place the created file and a webxml value indicating the location of the web.xml file that is to accompany the WAR, in this case the one corresponding to Listing 2-26.

Nested inside the <war> task are two <lib> declarations indicating what files will be placed within the WAR's lib directory, which is where all dependent JAR files are automatically picked up by an application server/container. Among the included JAR files is the helloworld.jar file, which includes the application's classes, as well as the various JARS for Spring, JPA, Apache Tiles, and so on needed to properly execute the application.

Capping off this Ant listing is <webinf>,which copies all the application's descriptors to the WAR's WEB-INF directory; <metainf>, which copies the application's context.xml file (the container's JNDI data source configuration) to the WAR's META-INF directory, and <zipfileset>, which copies the application's GUI files (Apache Tiles, JSP, and CSS) to the root directory of the WAR.

By appending the previous Ant listing to the existing ch2 target you created when testing your domain model (Listing 2-14) and reinvoking the command ant ch2,a WAR file by the name springhelloworld.war will be created under the subdirectory dist/ch2.

That's it! Now that your WAR file is ready, it's time to see the actual application on the Web.

Deploying on the Web

In order to deploy your Spring application on the Web, you will need to make two final adjustments to the infrastructure software that will support it: the RDBMS MySQL and Apache Tomcat.

Prepopulating the RDBMS with Data

Since the Spring application displays data from an RDBMS, you will to prepopulate it with a data set in order to show "Hello World" messages upon visiting it. Listing 2-31 contains a script used to prepopulate MySQL with the relational tables needed by the application.

Example 2-31. SQL Script helloworld.sql for Prepopulating the RDBMS

CREATE TABLE `HelloWorld` (
  `id` bigint(20) NOT NULL,
  `language` varchar(255) default NULL,
  `message` varchar(255) default NULL,
  `transdate` date default NULL,
  `translator_id` bigint(20) default NULL,
  PRIMARY KEY  (`id`),
  KEY `I_HLLWRLD_TRANSLATOR` (`translator_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `HelloWorld` VALUES (51,'Italian','Ciao Monde!','2008-05-27',2),
SQL Script helloworld.sql for Prepopulating the RDBMS
(52,'Spanish','Hola Mundo!','2008-05-27',1),(53,'English','Hello World!',
SQL Script helloworld.sql for Prepopulating the RDBMS
'2008-05-27',5),(54,'French','Bonjour Monde!','2008-05-27',3),
SQL Script helloworld.sql for Prepopulating the RDBMS
(55,'German','Hallo Welt!','2008-05-27',4); CREATE TABLE `OPENJPA_SEQUENCE_TABLE` ( `ID` tinyint(4) NOT NULL, `SEQUENCE_VALUE` bigint(20) default NULL, PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; INSERT INTO `OPENJPA_SEQUENCE_TABLE` VALUES (0,101); CREATE TABLE `Person` ( `id` bigint(20) NOT NULL, `FNAME` varchar(255) default NULL, `hourlyRate` double default NULL, `LNAME` varchar(255) default NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; INSERT INTO `Person` VALUES (1,'Carlos',40,'Perez'),(2,'Dino',45,'Casiraghi'),
SQL Script helloworld.sql for Prepopulating the RDBMS
(3,'Pierre',40,'LeClair'),(4,'Franz',45,'Becker'),(5,'John',45,'Smith'),

Before you actually prepopulate the RDBMS with these relation tables and values, a short note on their meaning: the Person and HelloWorld tables are of course in line with the domain model's POJO names, but you may be wondering about that table named OPENJPA_SEQUENCE_NAME.

This last table accommodates the default behavior of the JPA Entity Manager used in the application, Open JPA, and its mapping behavior to the MySQL RDBMS, all based on the annotations used to decorate the domain model.

Back when you annotated the HelloWorld and Person classes (Listings 2-6 and 2-7),upon using the annotation @Id @GeneratedValue, no strategy was specified to generate the IDs for persisting objects in these classes. In Open JPA's case as it specifically relates to MySQL, the default behavior is to consult a table by the name OPENJPA_SEQUENCE_TABLE in order to obtain a unique ID necessary to persist entity objects.

Be advised that this behavior is highly specific to both the JPA Entity Manager and RDBMS you are using. Other JPA/RDBMS combinations may rely on different table naming conventions, the use of an RDBMS sequence, or some other variation. And of course, all this default behavior could have been avoided if the JPA @GeneratedValue annotation in each class provided a strategy indicating a preexisting table or sequence to use as an ID generation source.

Next, you need to process the script so the data set makes its way to the application's database instance. While in a system shell, execute the following instruction: mysql -u hello -pworld -D springosgi < helloworld.sql—where helloworld.sql is the file containing the code from Listing 2-31. This will attempt to connect to the database instance named springosgi with the credentials you created at the outset, and insert the contents of the script helloworld.sql into the respective instance.

After the successful execution of the RDBMS script, MySQL should be prepared to offer data to the Spring application. Next, you need to prepare the hosting environment: Apache Tomcat.

Configuring Apache Tomcat

Apache Tomcat requires the incorporation of two JAR files into its underlying structure to properly execute the application, one to support the MySQL database and another to support Spring's operation within the application container itself. The steps are as follows:

  1. Copy spring-tomcat-weaver.jar: you need to copy this file located under the subdirectory /dist/weaving/ within the Spring with dependencies download over to $TOMCAT_HOME/server/lib/, where $TOMCAT_HOME is the root directory for Apache Tomcat.

  2. Copy mysql-connector-java-bin.jar: you need to copy this file located under the root directory within the MySQL Connector/J driver download over to $TOMCAT_HOME/common/lib/, where $TOMCAT_HOME is the root directory for Apache Tomcat.

  3. Next, you need to copy the springhelloworld.war file containing the application over to Apache Tomcat's webapps subdirectory, also located in the root directory of Apache Tomcat.

Once these three files are in place, you're ready to start up Apache Tomcat and fire up a browser to see your application.

Starting Apache Tomcat

Move over to the bin directory inside Apache Tomcat and execute java -jar bootstrap.jar.Once you do this, Apache Tomcat will automatically expand springhelloworld.war,outputting a deployment message to the screen and making the application accessible under a virtual directory by the WAR's name.

Upon completion, Apache Tomcat will be running under port 8080 of your localhost, so if you open up a browser and point it toward http://localhost:8080/springhelloworld/,you will be able to access the Hello World Spring application.

Summary

In this chapter you learned how Spring emerged as a grassroots movement to address many of the shortcomings present in the earlier versions of the Java 2 Enterprise Edition (J2EE)—now Java Enterprise Edition (Java EE)—offering a fresh approach to building enterprise Java applications based on the concepts of IoC/DI and POJO architectures.

You also explored the many advantages to using a POJO-based architecture in enterprise applications, favoring such things as simplicity, maintenance, testing, and reuse. Additionally, you gained perspective on the numerous areas the Spring Framework has influenced since its inception, going even beyond the Java platform.

Later you experienced firsthand how to create a domain model based on POJO principles, which included enabling the model to use an RDBMS and leveraging Java's de facto object-relational API, JPA.

Then you performed both unit testing and integration testing on the same domain model using the Java JUnit framework and other artifacts provided by the Spring Framework. This was followed by a brief incursion into Spring's support for the MVC and AJAX type designs, both of which are staples in today's web applications.

Finally, you learned how to actually deploy a WAR that included application classes, JSPs, Apache Tiles, CSS, and configuration files created during the chapter, coming away with a live end-to-end Spring application using JPA and Spring's MVC, with Apache Tomcat serving as the Java EE container and MySQL as the RDBMS.



[5] Rod Johnson, J2EE Design and Development (Indianapolis, Indiana: Wrox, 2002)

[6] Rod Johnson, Juergen Hoeller, J2EE Development without EJB (Indianapolis, Indiana: Wrox, 2004)

[7] Martin Fowler, InversionOfControl definition,http://martinfowler.com/bliki/InversionOfControl.html

[8] Martin Fowler, POJO definition, http://martinfowler.com/bliki/POJO.html

[9] Wikipedia, "Test-driven Development," http://en.wikipedia.org/wiki/Test-driven_development

[10] http://java.sun.com/javaee/overview/faq/persistence.jsp

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.217.254.118