This spring tutorial provides in-depth concepts of Spring Framework with simplified examples. It was developed by Rod Johnson in 2003. Spring framework makes the easy development of JavaEE application.
It is helpful for beginners and experienced persons.
Spring Framework
Spring is a lightweight framework. It can be thought of as a framework of frameworks because it provides support to various frameworks such as Struts, Hibernate, Tapestry, EJB, JSF etc. The framework, in broader sense, can be defined as a structure where we find solution of the various technical problems.
The Spring framework comprises several modules such as IOC, AOP, DAO, Context, ORM, WEB MVC etc. We will learn these modules in next page. Let's understand the IOC and Dependency Injection first.
Spring is the most popular application development framework for enterprise Java. Millions of developers around the world use Spring Framework to create high performing, easily testable, reusable code.
Spring framework is an open source Java platform and it was initially written by Rod Johnson and was first released under the Apache 2.0 license in June 2003.
Spring is lightweight when it comes to size and transparency. The basic version of spring framework is around 2MB.
The core features of the Spring Framework can be used in developing any Java application, but there are extensions for building web applications on top of the Java EE platform. Spring framework targets to make J2EE development easier to use and promote good programming practice by enabling a POJO-based programming model.
Benefits of Using Spring Framework:
Following is the list of few of the great benefits of using Spring Framework:
Spring enables developers to develop enterprise-class applications using POJOs. The benefit of using only POJOs is that you do not need an EJB container product such as an application server but you have the option of using only a robust servlet container such as Tomcat or some commercial product.
Spring is organized in a modular fashion. Even though the number of packages and classes are substantial, you have to worry only about ones you need and ignore the rest.
Spring does not reinvent the wheel instead, it truly makes use of some of the existing technologies like several ORM frameworks, logging frameworks, JEE, Quartz and JDK timers, other view technologies.
Testing an application written with Spring is simple because environment-dependent code is moved into this framework. Furthermore, by using JavaBean-style POJOs, it becomes easier to use dependency injection for injecting test data.
Spring's web framework is a well-designed web MVC framework, which provides a great alternative to web frameworks such as Struts or other over engineered or less popular web frameworks.
Spring provides a convenient API to translate technology-specific exceptions (thrown by JDBC, Hibernate, or JDO, for example) into consistent, unchecked exceptions.
Lightweight IoC containers tend to be lightweight, especially when compared to EJB containers, for example. This is beneficial for developing and deploying applications on computers with limited memory and CPU resources.
Spring provides a consistent transaction management interface that can scale down to a local transaction (using a single database, for example) and scale up to global transactions (using JTA, for example).
The above mentioned benefits are in briefly :
1) Predefined Templates
Spring framework provides templates for JDBC, Hibernate, JPA etc. technologies. So there is no need to write too much code. It hides the basic steps of these technologies.
Let's take the example of JdbcTemplate, you don't need to write the code for exception handling, creating connection, creating statement, committing transaction, closing connection etc. You need to write the code of executing query only. Thus, it save a lot of JDBC code.
2) Loose Coupling
The Spring applications are loosely coupled because of dependency injection.
3) Easy to test
The Dependency Injection makes easier to test the application. The EJB or Struts application require server to run the application but Spring framework doesn't require server.
4) Lightweight
Spring framework is lightweight because of its POJO implementation. The Spring Framework doesn't force the programmer to inherit any class or implement any interface. That is why it is said non-invasive.
5) Fast Development
The Dependency Injection feature of Spring Framework and it support to various frameworks makes the easy development of JavaEE application.
6) Powerful abstraction
It provides powerful abstraction to JavaEE specifications such as JMS, JDBC, JPA and JTA.
7) Declarative support
It provides declarative support for caching, validation, transactions and formatting.
Spring Modules
- Spring Modules
- Test
- Spring Core Container
- AOP, Aspects and Instrumentation
- Data Access / Integration
- Web
1. Spring Modules Diagram : :
The Spring framework comprises of many modules such as core, beans, context, expression language, AOP, Aspects, Instrumentation, JDBC, ORM, OXM, JMS, Transaction, Web, Servlet, Struts etc. These modules are grouped into Test, Core Container, AOP, Aspects, Instrumentation, Data Access / Integration, Web (MVC / Remoting) as displayed in the following diagram.
2. Spring Test : :
This layer provides support of testing with JUnit and TestNG.
Spring framework was designed based on agile testing strategies to help developers follow sound design and effective unit testing best practices. It also provides a great support for running integration tests outside the application server. Spring is a non-invasive framework in the sense that when we use Spring, there is a minimal dependency of application code on the framework. We can configure application objects as plain java classes (POJOs) without having to extend any Spring specific classes (Note: When you use Spring template helper classes such as JDBCTemplate, JNDITemplate, HibernateDaoSupport etc, you are adding the dependency on the Spring framework). We can even configure any legacy classes that were written prior to the existence of Spring.
Spring framework in general, and Spring Testing module in particular support the following aspects:
Isolation:
Spring gives J2EE developers the flexibility to test java classes in isolation by injecting mock implementations. For example, we can test a service class using a mock implementation of the corresponding Repository class. This way, we can test business logic in the service class without worrying about the persistence details of connecting to a database.
Inversion of Control:
The framework provides sophisticated configuration management for POJOs. Spring IoC container can manage fine or coarse grained java classes. It uses a bean factory to instantiate application objects and wire them together using constructor or setter injection mechanisms.
Data Access:
It provides a nice persistence architecture for data access and a good hierarchy of data access exceptions. It provides helper classes (such as JdbcTemplate, HibernateTemplate, TopLinkTemplate, JpaTemplate) to work with the leading persistence frameworks.
Transaction Management:
Spring provides a nice abstraction framework for managing transactions (both local and global). This abstraction provides a consistent programming model in a wide range of development environments and is the basis for Spring's declarative and programmatic transaction management.
Integration Testing using Spring
Spring configuration, dependency injection (DI), data access (CRUD), and transaction management are some of the concerns that we can test outside the server environment using Spring Testing framework. The data access tests are executed against a real database so no need to use any mock objects in these tests.
Spring context load time may not be an issue in small to medium size web applications. But for a large size enterprise application, it could take significant time to instantiate the classes in the application. Also, the overhead of running every single test case in every single test fixture leads to slower overall test runs and adversely affects developer productivity. Keeping these concerns in mind, Spring development team wrote some test classes that can be used as integration tests running outside the container. Since these test classes are extensions of JUnit API, we get all the benefits of JUnit right out of the box when we use the Spring test classes. These test classes setup a transaction for each test method and automatically cleanup (rolling back the transaction at end of each method) eliminating the necessity for any database setup and teardown tasks.
Following is a list of items we can verify when we run integration tests in a Spring application:
- Loading of Spring contexts and management of the contexts by caching loaded contexts between execution of each test case. Also, verify correct wiring of application contexts by Spring IoC container.
- Dependency Injection of test fixtures and Spring configuration details (To verify if a specific data access (Repository) class configuration is loaded correctly).
- Convenience variables for data access and CRUD operations (The logic of data access class to test database select and updates).
- Transaction management.
- ORM mapping file configuration (Verify if everything related to a persistence object is mapped correctly and correct lazy-loading semantics are in place).
We can run integration tests just like JUnit tests. They are slower to run compared to unit tests because we are testing the code at integration level rather than just at a class level. But these integration tests are lot faster to execute than the tests created using in-container testing frameworks such as JUnitEE or Cactus which rely on deployment of the application to the container before the tests can be executed.
Spring integration test classes were designed to address various testing concerns so there are different test classes in org.springframework.test package. Following table shows some of the test classes provided in Spring framework for integration testing and in what scenarios they can be used.
3. Spring Core Container : :
The Core Container consists of the spring-core
,
spring-beans
, spring-context
, spring-context-support
, and spring-expression
(Spring Expression Language) modules.
The spring-core
and spring-beans
modules provide the fundamental
parts of the framework, including the IoC and Dependency Injection features. The
BeanFactory
is a sophisticated implementation of the factory pattern. It removes the
need for programmatic singletons and allows you to decouple the configuration and
specification of dependencies from your actual program logic.
The Core module provides the fundamental parts of the framework, including the IoC and Dependency Injection features.
The Bean module provides BeanFactory which is a sophisticated implementation of the factory pattern.
The Context module builds on the solid base provided by the Core and Beans modules and it is a medium to access any objects defined and configured. The ApplicationContext interface is the focal point of the Context module.
The SpEL module provides a powerful expression language for querying and manipulating an object graph at runtime.
The Spring Core container contains core, beans, context and expression language (EL) modules.
Spring Core and Beans : :
These modules provide IOC and Dependency Injection features.
Inversion Of Control (IOC) and Dependency Injection (DI):
The technology that Spring is most identified with is the Dependency Injection (DI) flavor of Inversion of Control. The Inversion of Control (IoC) is a general concept, and it can be expressed in many different ways and Dependency Injection is merely one concrete example of Inversion of Control.
When writing a complex Java application, application classes should be as independent as possible of other Java classes to increase the possibility to reuse these classes and to test them independently of other classes while doing unit testing. Dependency Injection helps in gluing these classes together and same time keeping them independent.
What is dependency injection exactly? Let's look at these two words separately. Here the dependency part translates into an association between two classes. For example, class A is dependent on class B. Now, let's look at the second part, injection. All this means is that class B will get injected into class A by the IoC.
Dependency injection can happen in the way of passing parameters to the constructor or by post-construction using setter methods. As Dependency Injection is the heart of Spring Framework, so I will explain this concept in a separate chapter with a nice example.
Spring Context : :
This module supports internationalization (I18N), EJB, JMS, Basic Remoting.
The Context (spring-context
) module builds on the solid
base provided by the Core and Beans modules: it is a means to
access objects in a framework-style manner that is similar to a JNDI registry. The
Context module inherits its features from the Beans module and adds support for
internationalization (using, for example, resource bundles), event propagation, resource
loading, and the transparent creation of contexts by, for example, a Servlet container.
The Context module also supports Java EE features such as EJB, JMX, and basic remoting.
The ApplicationContext
interface is the focal point of the Context module.
spring-context-support
provides support for integrating common third-party libraries
into a Spring application context for caching (EhCache, Guava, JCache), mailing
(JavaMail), scheduling (CommonJ, Quartz) and template engines (FreeMarker, JasperReports,
Velocity).
Spring Expression Language : :
It is an extension to the EL defined in JSP. It provides support to setting and getting property values, method invocation, accessing collections and indexers, named variables, logical and arithmetic operators, retrieval of objects by name etc.
The spring-expression
module provides a powerful Expression
Language for querying and manipulating an object graph at runtime. It is an extension
of the unified expression language (unified EL) as specified in the JSP 2.1
specification. The language supports setting and getting property values, property
assignment, method invocation, accessing the content of arrays, collections and indexers,
logical and arithmetic operators, named variables, and retrieval of objects by name from
Spring’s IoC container. It also supports list projection and selection as well as common
list aggregations.
4. AOP, Aspects and Instrumentation : :
These modules support aspect oriented programming implementation where you can use Advices, Pointcuts etc. to decouple the code.
The aspects module provides support to integration with AspectJ.
The instrumentation module provides support to class instrumentation and classloader implementations.
One of the key components of Spring Framework is the Aspect oriented programming (AOP) framework. Aspect Oriented Programming entails breaking down program logic into distinct parts called so-called concerns. The functions that span multiple points of an application are called cross-cutting concerns and these cross-cutting concerns are conceptually separate from the application's business logic. There are various common good examples of aspects like logging, auditing, declarative transactions, security, and caching etc.
The key unit of modularity in OOP is the class, whereas in AOP the unit of modularity is the aspect. Dependency Injection helps you decouple your application objects from each other and AOP helps you decouple cross-cutting concerns from the objects that they affect. AOP is like triggers in programming languages such as Perl, .NET, Java and others.
Spring AOP module provides interceptors to intercept an application, for example, when a method is executed, you can add extra functionality before or after the method execution.
AOP Terminologies:
Before we start working with AOP, let us become familiar with the AOP concepts and terminology. These terms are not specific to Spring, rather they are related to AOP.
Terms | Description |
---|---|
Aspect | A module which has a set of APIs providing cross-cutting requirements. For example, a logging module would be called AOP aspect for logging. An application can have any number of aspects depending on the requirement. |
Join point | This represents a point in your application where you can plug-in AOP aspect. You can also say, it is the actual place in the application where an action will be taken using Spring AOP framework. |
Advice | This is the actual action to be taken either before or after the method execution. This is actual piece of code that is invoked during program execution by Spring AOP framework. |
Pointcut | This is a set of one or more joinpoints where an advice should be executed. You can specify pointcuts using expressions or patterns as we will see in our AOP examples. |
Introduction | An introduction allows you to add new methods or attributes to existing classes. |
Target object | The object being advised by one or more aspects, this object will always be a proxied object. Also referred to as the advised object. |
Weaving | Weaving is the process of linking aspects with other application types or objects to create an advised object. This can be done at compile time, load time, or at runtime. |
Types of Advice
Spring aspects can work with five kinds of advice mentioned below:
Advice | Description |
---|---|
before | Run advice before the a method execution. |
after | Run advice after the a method execution regardless of its outcome. |
after-returning | Run advice after the a method execution only if method completes successfully. |
after-throwing | Run advice after the a method execution only if method exits by throwing an exception. |
around | Run advice before and after the advised method is invoked. |
Custom Aspects Implementation
Spring supports the @AspectJ annotation style approach and the schema-based approach to implement custom aspects. These two approaches have been explained in detail in the following two sub chapters
Approach | Description |
---|---|
XML Schema based | Aspects are implemented using regular classes along with XML based configuration. |
@AspectJ based | @AspectJ refers to a style of declaring aspects as regular Java classes annotated with Java 5 annotations. |
5. Data Access/Integration : :
The Data Access/Integration layer consists of the JDBC, ORM, OXM, JMS and Transaction modules whose detail is as follows:
The JDBC module provides a JDBC-abstraction layer that removes the need to do tedious JDBC related coding.
The ORM module provides integration layers for popular object-relational mapping APIs, including JPA, JDO, Hibernate, and iBatis.
The OXM module provides an abstraction layer that supports Object/XML mapping implementations for JAXB, Castor, XMLBeans, JiBX and XStream.
The Java Messaging Service JMS module contains features for producing and consuming messages.
The Transaction module supports programmatic and declarative transaction management for classes that implement special interfaces and for all your POJOs.
This group comprises of JDBC, ORM, OXM, JMS and Transaction modules. These modules basically provide support to interact with the database.
The value-add provided by the Spring Framework JDBC abstraction is perhaps best shown by the sequence of actions outlined in the table below. The table shows what actions Spring will take care of and which actions are the responsibility of you, the application developer.
Table Spring JDBC - who does what?
Action | Spring | You |
---|---|---|
Define connection parameters. | X | |
Open the connection. | X | |
Specify the SQL statement. | X | |
Declare parameters and provide parameter values | X | |
Prepare and execute the statement. | X | |
Set up the loop to iterate through the results (if any). | X | |
Do the work for each iteration. | X | |
Process any exception. | X | |
Handle transactions. | X | |
Close the connection, statement and resultset. | X |
The Spring Framework takes care of all the low-level details that can make JDBC such a tedious API to develop with.
You can choose among several approaches to form the basis for your JDBC database access. In addition to three flavors of the JdbcTemplate, a new SimpleJdbcInsert and SimplejdbcCall approach optimizes database metadata, and the RDBMS Object style takes a more object-oriented approach similar to that of JDO Query design. Once you start using one of these approaches, you can still mix and match to include a feature from a different approach. All approaches require a JDBC 2.0-compliant driver, and some advanced features require a JDBC 3.0 driver.
- JdbcTemplate is the classic Spring JDBC approach and the most popular. This "lowest level" approach and all others use a JdbcTemplate under the covers.
-
NamedParameterJdbcTemplate wraps a
JdbcTemplate
to provide named parameters instead of the traditional JDBC "?" placeholders. This approach provides better documentation and ease of use when you have multiple parameters for an SQL statement. - SimpleJdbcInsert and SimpleJdbcCall optimize database metadata to limit the amount of necessary configuration. This approach simplifies coding so that you only need to provide the name of the table or procedure and provide a map of parameters matching the column names. This only works if the database provides adequate metadata. If the database doesn’t provide this metadata, you will have to provide explicit configuration of the parameters.
- RDBMS Objects including MappingSqlQuery, SqlUpdate and StoredProcedure requires you to create reusable and thread-safe objects during initialization of your data access layer. This approach is modeled after JDO Query wherein you define your query string, declare parameters, and compile the query. Once you do that, execute methods can be called multiple times with various parameter values passed in.
The Spring Framework’s JDBC abstraction framework consists of four different packages,
namely core
, datasource
, object
, and support
.
The org.springframework.jdbc.core
package contains the JdbcTemplate
class and its
various callback interfaces, plus a variety of related classes. A subpackage named
org.springframework.jdbc.core.simple
contains the SimpleJdbcInsert
and
SimpleJdbcCall
classes. Another subpackage named
org.springframework.jdbc.core.namedparam
contains the NamedParameterJdbcTemplate
class and the related support classes.
The org.springframework.jdbc.datasource
package contains a utility class for easy
DataSource
access, and various simple DataSource
implementations that can be used for
testing and running unmodified JDBC code outside of a Java EE container. A subpackage
named org.springfamework.jdbc.datasource.embedded
provides support for creating
embedded databases using Java database engines such as HSQL, H2, and Derby.
The org.springframework.jdbc.object
package contains classes that represent RDBMS
queries, updates, and stored procedures as thread-safe, reusable objects. See
. This approach is modeled by JDO, although objects returned by queries
are naturally disconnected from the database. This higher level of JDBC abstraction
depends on the lower-level abstraction in the org.springframework.jdbc.core
package.
The org.springframework.jdbc.support
package provides SQLException
translation
functionality and some utility classes. Exceptions thrown during JDBC processing are
translated to exceptions defined in the org.springframework.dao
package. This means
that code using the Spring JDBC abstraction layer does not need to implement JDBC or
RDBMS-specific error handling. All translated exceptions are unchecked, which gives you
the option of catching the exceptions from which you can recover while allowing other
exceptions to be propagated to the caller.
The JdbcTemplate
class is the central class in the JDBC core package. It handles the
creation and release of resources, which helps you avoid common errors such as
forgetting to close the connection. It performs the basic tasks of the core JDBC
workflow such as statement creation and execution, leaving application code to provide
SQL and extract results. The JdbcTemplate
class executes SQL queries, update
statements and stored procedure calls, performs iteration over ResultSets and
extraction of returned parameter values. It also catches JDBC exceptions and translates
them to the generic, more informative, exception hierarchy defined in the
org.springframework.dao
package.
When you use the JdbcTemplate
for your code, you only need to implement callback
interfaces, giving them a clearly defined contract. The PreparedStatementCreator
callback interface creates a prepared statement given a Connection
provided by this
class, providing SQL and any necessary parameters. The same is true for the
CallableStatementCreator
interface, which creates callable statements. The
RowCallbackHandler
interface extracts values from each row of a ResultSet
.
The JdbcTemplate
can be used within a DAO implementation through direct instantiation
with a DataSource
reference, or be configured in a Spring IoC container and given to
DAOs as a bean reference.
Note | |
---|---|
The |
All SQL issued by this class is logged at the DEBUG
level under the category
corresponding to the fully qualified class name of the template instance (typically
JdbcTemplate
, but it may be different if you are using a custom subclass of the
JdbcTemplate
class).
This section provides some examples of JdbcTemplate
class usage. These examples are
not an exhaustive list of all of the functionality exposed by the JdbcTemplate
; see
the attendant javadocs for that.
Here is a simple query for getting the number of rows in a relation:
int rowCount = this.jdbcTemplate.queryForObject("select count(*) from t_actor", Integer.class);
A simple query using a bind variable:
int countOfActorsNamedJoe = this.jdbcTemplate.queryForObject( "select count(*) from t_actor where first_name = ?", Integer.class, "Joe");
Querying for a String
:
String lastName = this.jdbcTemplate.queryForObject( "select last_name from t_actor where id = ?", new Object[]{1212L}, String.class);
Querying and populating a single domain object:
Actor actor = this.jdbcTemplate.queryForObject( "select first_name, last_name from t_actor where id = ?", new Object[]{1212L}, new RowMapper<Actor>() { public Actor mapRow(ResultSet rs, int rowNum) throws SQLException { Actor actor = new Actor(); actor.setFirstName(rs.getString("first_name")); actor.setLastName(rs.getString("last_name")); return actor; } });
Querying and populating a number of domain objects:
List<Actor> actors = this.jdbcTemplate.query( "select first_name, last_name from t_actor", new RowMapper<Actor>() { public Actor mapRow(ResultSet rs, int rowNum) throws SQLException { Actor actor = new Actor(); actor.setFirstName(rs.getString("first_name")); actor.setLastName(rs.getString("last_name")); return actor; } });
If the last two snippets of code actually existed in the same application, it would make
sense to remove the duplication present in the two RowMapper
anonymous inner classes,
and extract them out into a single class (typically a static
nested class) that can
then be referenced by DAO methods as needed. For example, it may be better to write the
last code snippet as follows:
public List<Actor> findAllActors() { return this.jdbcTemplate.query( "select first_name, last_name from t_actor", new ActorMapper()); } private static final class ActorMapper implements RowMapper<Actor> { public Actor mapRow(ResultSet rs, int rowNum) throws SQLException { Actor actor = new Actor(); actor.setFirstName(rs.getString("first_name")); actor.setLastName(rs.getString("last_name")); return actor; } }
You use the update(..)
method to perform insert, update and delete operations.
Parameter values are usually provided as var args or alternatively as an object array.
this.jdbcTemplate.update( "insert into t_actor (first_name, last_name) values (?, ?)", "Leonor", "Watling");
this.jdbcTemplate.update( "update t_actor set last_name = ? where id = ?", "Banjo", 5276L);
this.jdbcTemplate.update( "delete from actor where id = ?", Long.valueOf(actorId));
You can use the execute(..)
method to execute any arbitrary SQL, and as such the
method is often used for DDL statements. It is heavily overloaded with variants taking
callback interfaces, binding variable arrays, and so on.
this.jdbcTemplate.execute("create table mytable (id integer, name varchar(100))");
The following example invokes a simple stored procedure. More sophisticated stored procedure support is covered later.
this.jdbcTemplate.update( "call SUPPORT.REFRESH_ACTORS_SUMMARY(?)", Long.valueOf(unionId));
Instances of the JdbcTemplate
class are threadsafe once configured. This is
important because it means that you can configure a single instance of a JdbcTemplate
and then safely inject this shared reference into multiple DAOs (or repositories).
The JdbcTemplate
is stateful, in that it maintains a reference to a DataSource
, but
this state is not conversational state.
A common practice when using the JdbcTemplate
class (and the associated
NamedParameterJdbcTemplate classes) is to
configure a DataSource
in your Spring configuration file, and then dependency-inject
that shared DataSource
bean into your DAO classes; the JdbcTemplate
is created in
the setter for the DataSource
. This leads to DAOs that look in part like the following:
public class JdbcCorporateEventDao implements CorporateEventDao { private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } // JDBC-backed implementations of the methods on the CorporateEventDao follow... }
The corresponding configuration might look like this.
<?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/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <bean id="corporateEventDao" class="com.example.JdbcCorporateEventDao"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <context:property-placeholder location="jdbc.properties"/> </beans>
An alternative to explicit configuration is to use component-scanning and annotation
support for dependency injection. In this case you annotate the class with @Repository
(which makes it a candidate for component-scanning) and annotate the DataSource
setter
method with @Autowired
.
@Repository public class JdbcCorporateEventDao implements CorporateEventDao { private JdbcTemplate jdbcTemplate; @Autowired public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } // JDBC-backed implementations of the methods on the CorporateEventDao follow... }
The corresponding XML configuration file would look like the following:
<?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/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- Scans within the base package of the application for @Component classes to configure as beans --> <context:component-scan base-package="org.springframework.docs.test" /> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <context:property-placeholder location="jdbc.properties"/> </beans>
If you are using Spring’s JdbcDaoSupport
class, and your various JDBC-backed DAO classes
extend from it, then your sub-class inherits a setDataSource(..)
method from the
JdbcDaoSupport
class. You can choose whether to inherit from this class. The
JdbcDaoSupport
class is provided as a convenience only.
Regardless of which of the above template initialization styles you choose to use (or
not), it is seldom necessary to create a new instance of a JdbcTemplate
class each
time you want to execute SQL. Once configured, a JdbcTemplate
instance is threadsafe.
You may want multiple JdbcTemplate
instances if your application accesses multiple
databases, which requires multiple DataSources
, and subsequently multiple differently
configured JdbcTemplates
.
The NamedParameterJdbcTemplate
class adds support for programming JDBC statements
using named parameters, as opposed to programming JDBC statements using only classic
placeholder ( '?'
) arguments. The NamedParameterJdbcTemplate
class wraps a
JdbcTemplate
, and delegates to the wrapped JdbcTemplate
to do much of its work. This
section describes only those areas of the NamedParameterJdbcTemplate
class that differ
from the JdbcTemplate
itself; namely, programming JDBC statements using named
parameters.
// some JDBC-backed DAO class... private NamedParameterJdbcTemplate namedParameterJdbcTemplate; public void setDataSource(DataSource dataSource) { this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); } public int countOfActorsByFirstName(String firstName) { String sql = "select count(*) from T_ACTOR where first_name = :first_name"; SqlParameterSource namedParameters = new MapSqlParameterSource("first_name", firstName); return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class); }
Notice the use of the named parameter notation in the value assigned to the sql
variable, and the corresponding value that is plugged into the namedParameters
variable (of type MapSqlParameterSource
).
Alternatively, you can pass along named parameters and their corresponding values to a
NamedParameterJdbcTemplate
instance by using the Map
-based style.The remaining
methods exposed by the NamedParameterJdbcOperations
and implemented by the
NamedParameterJdbcTemplate
class follow a similar pattern and are not covered here.
The following example shows the use of the Map
-based style.
// some JDBC-backed DAO class... private NamedParameterJdbcTemplate namedParameterJdbcTemplate; public void setDataSource(DataSource dataSource) { this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); } public int countOfActorsByFirstName(String firstName) { String sql = "select count(*) from T_ACTOR where first_name = :first_name"; Map<String, String> namedParameters = Collections.singletonMap("first_name", firstName); return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class); }
One nice feature related to the NamedParameterJdbcTemplate
(and existing in the same
Java package) is the SqlParameterSource
interface. You have already seen an example of
an implementation of this interface in one of the previous code snippet (the
MapSqlParameterSource
class). An SqlParameterSource
is a source of named parameter
values to a NamedParameterJdbcTemplate
. The MapSqlParameterSource
class is a very
simple implementation that is simply an adapter around a java.util.Map
, where the keys
are the parameter names and the values are the parameter values.
Another SqlParameterSource
implementation is the BeanPropertySqlParameterSource
class. This class wraps an arbitrary JavaBean (that is, an instance of a class that
adheres to the
JavaBean conventions), and uses the properties of the wrapped JavaBean as the source
of named parameter values.
public class Actor { private Long id; private String firstName; private String lastName; public String getFirstName() { return this.firstName; } public String getLastName() { return this.lastName; } public Long getId() { return this.id; } // setters omitted... }
// some JDBC-backed DAO class... private NamedParameterJdbcTemplate namedParameterJdbcTemplate; public void setDataSource(DataSource dataSource) { this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); } public int countOfActors(Actor exampleActor) { // notice how the named parameters match the properties of the above 'Actor' class String sql = "select count(*) from T_ACTOR where first_name = :firstName and last_name = :lastName"; SqlParameterSource namedParameters = new BeanPropertySqlParameterSource(exampleActor); return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class); }
Remember that the NamedParameterJdbcTemplate
class wraps a classic JdbcTemplate
template; if you need access to the wrapped JdbcTemplate
instance to access
functionality only present in the JdbcTemplate
class, you can use the
getJdbcOperations()
method to access the wrapped JdbcTemplate
through the
JdbcOperations
interface.
SQLExceptionTranslator
is an interface to be implemented by classes that can translate
between SQLExceptions
and Spring’s own org.springframework.dao.DataAccessException
,
which is agnostic in regard to data access strategy. Implementations can be generic (for
example, using SQLState codes for JDBC) or proprietary (for example, using Oracle error
codes) for greater precision.
SQLErrorCodeSQLExceptionTranslator
is the implementation of SQLExceptionTranslator
that is used by default. This implementation uses specific vendor codes. It is more
precise than the SQLState
implementation. The error code translations are based on
codes held in a JavaBean type class called SQLErrorCodes
. This class is created and
populated by an SQLErrorCodesFactory
which as the name suggests is a factory for
creating SQLErrorCodes
based on the contents of a configuration file named
sql-error-codes.xml
. This file is populated with vendor codes and based on the
DatabaseProductName
taken from the DatabaseMetaData
. The codes for the actual
database you are using are used.
The SQLErrorCodeSQLExceptionTranslator
applies matching rules in the following sequence:
Note | |
---|---|
The |
-
Any custom translation implemented by a subclass. Normally the provided concrete
SQLErrorCodeSQLExceptionTranslator
is used so this rule does not apply. It only applies if you have actually provided a subclass implementation. -
Any custom implementation of the
SQLExceptionTranslator
interface that is provided as thecustomSqlExceptionTranslator
property of theSQLErrorCodes
class. -
The list of instances of the
CustomSQLErrorCodesTranslation
class, provided for thecustomTranslations
property of theSQLErrorCodes
class, are searched for a match. - Error code matching is applied.
-
Use the fallback translator.
SQLExceptionSubclassTranslator
is the default fallback translator. If this translation is not available then the next fallback translator is theSQLStateSQLExceptionTranslator
.
You can extend SQLErrorCodeSQLExceptionTranslator:
public class CustomSQLErrorCodesTranslator extends SQLErrorCodeSQLExceptionTranslator { protected DataAccessException customTranslate(String task, String sql, SQLException sqlex) { if (sqlex.getErrorCode() == -12345) { return new DeadlockLoserDataAccessException(task, sqlex); } return null; } }
In this example, the specific error code -12345
is translated and other errors are
left to be translated by the default translator implementation. To use this custom
translator, it is necessary to pass it to the JdbcTemplate
through the method
setExceptionTranslator
and to use this JdbcTemplate
for all of the data access
processing where this translator is needed. Here is an example of how this custom
translator can be used:
private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource) { // create a JdbcTemplate and set data source this.jdbcTemplate = new JdbcTemplate(); this.jdbcTemplate.setDataSource(dataSource); // create a custom translator and set the DataSource for the default translation lookup CustomSQLErrorCodesTranslator tr = new CustomSQLErrorCodesTranslator(); tr.setDataSource(dataSource); this.jdbcTemplate.setExceptionTranslator(tr); } public void updateShippingCharge(long orderId, long pct) { // use the prepared JdbcTemplate for this update this.jdbcTemplate.update("update orders" + " set shipping_charge = shipping_charge * ? / 100" + " where id = ?", pct, orderId); }
The custom translator is passed a data source in order to look up the error codes in
sql-error-codes.xml
.
Executing an SQL statement requires very little code. You need a DataSource
and a
JdbcTemplate
, including the convenience methods that are provided with the
JdbcTemplate
. The following example shows what you need to include for a minimal but
fully functional class that creates a new table:
import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate; public class ExecuteAStatement { private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } public void doExecute() { this.jdbcTemplate.execute("create table mytable (id integer, name varchar(100))"); } }
Some query methods return a single value. To retrieve a count or a specific value from
one row, use queryForObject(..)
. The latter converts the returned JDBC Type
to the
Java class that is passed in as an argument. If the type conversion is invalid, then an
InvalidDataAccessApiUsageException
is thrown. Here is an example that contains two
query methods, one for an int
and one that queries for a String
.
import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate; public class RunAQuery { private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } public int getCount() { return this.jdbcTemplate.queryForObject("select count(*) from mytable", Integer.class); } public String getName() { return this.jdbcTemplate.queryForObject("select name from mytable", String.class); } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } }
In addition to the single result query methods, several methods return a list with an
entry for each row that the query returned. The most generic method is
queryForList(..)
which returns a List
where each entry is a Map
with each entry in
the map representing the column value for that row. If you add a method to the above
example to retrieve a list of all the rows, it would look like this:
private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } public List<Map<String, Object>> getList() { return this.jdbcTemplate.queryForList("select * from mytable"); }
The list returned would look something like this:
[{name=Bob, id=1}, {name=Mary, id=2}]
The following example shows a column updated for a certain primary key. In this example, an SQL statement has placeholders for row parameters. The parameter values can be passed in as varargs or alternatively as an array of objects. Thus primitives should be wrapped in the primitive wrapper classes explicitly or using auto-boxing.
import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate; public class ExecuteAnUpdate { private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } public void setName(int id, String name) { this.jdbcTemplate.update("update mytable set name = ? where id = ?", name, id); } }
An update()
convenience method supports the retrieval of primary keys generated by the
database. This support is part of the JDBC 3.0 standard; see Chapter 13.6 of the
specification for details. The method takes a PreparedStatementCreator
as its first
argument, and this is the way the required insert statement is specified. The other
argument is a KeyHolder
, which contains the generated key on successful return from
the update. There is not a standard single way to create an appropriate
PreparedStatement
(which explains why the method signature is the way it is). The
following example works on Oracle but may not work on other platforms:
final String INSERT_SQL = "insert into my_test (name) values(?)"; final String name = "Rob"; KeyHolder keyHolder = new GeneratedKeyHolder(); jdbcTemplate.update( new PreparedStatementCreator() { public PreparedStatement createPreparedStatement(Connection connection) throws SQLException { PreparedStatement ps = connection.prepareStatement(INSERT_SQL, new String[] {"id"}); ps.setString(1, name); return ps; } }, keyHolder); // keyHolder.getKey() now contains the generated key
Spring obtains a connection to the database through a DataSource
. A DataSource
is
part of the JDBC specification and is a generalized connection factory. It allows a
container or a framework to hide connection pooling and transaction management issues
from the application code. As a developer, you need not know details about how to
connect to the database; that is the responsibility of the administrator that sets up
the datasource. You most likely fill both roles as you develop and test code, but you do
not necessarily have to know how the production data source is configured.
When using Spring’s JDBC layer, you obtain a data source from JNDI or you configure your own with a connection pool implementation provided by a third party. Popular implementations are Apache Jakarta Commons DBCP and C3P0. Implementations in the Spring distribution are meant only for testing purposes and do not provide pooling.
This section uses Spring’s DriverManagerDataSource
implementation, and several
additional implementations are covered later.
Note | |
---|---|
Only use the |
You obtain a connection with DriverManagerDataSource
as you typically obtain a JDBC
connection. Specify the fully qualified classname of the JDBC driver so that the
DriverManager
can load the driver class. Next, provide a URL that varies between JDBC
drivers. (Consult the documentation for your driver for the correct value.) Then provide
a username and a password to connect to the database. Here is an example of how to
configure a DriverManagerDataSource
in Java code:
DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("org.hsqldb.jdbcDriver"); dataSource.setUrl("jdbc:hsqldb:hsql://localhost:"); dataSource.setUsername("sa"); dataSource.setPassword("");
Here is the corresponding XML configuration:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <context:property-placeholder location="jdbc.properties"/>
The following examples show the basic connectivity and configuration for DBCP and C3P0. To learn about more options that help control the pooling features, see the product documentation for the respective connection pooling implementations.
DBCP configuration:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <context:property-placeholder location="jdbc.properties"/>
C3P0 configuration:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driverClassName}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <context:property-placeholder location="jdbc.properties"/>
6. Web : :
The Web layer consists of the Web, Web-MVC, Web-Socket, and Web-Portlet modules whose detail is as follows:
The Web module provides basic web-oriented integration features such as multipart file-upload functionality and the initialization of the IoC container using servlet listeners and a web-oriented application context.
The Web-MVC module contains Spring's model-view-controller (MVC) implementation for web applications.
The Web-Socket module provides support for WebSocket-based, two-way communication between client and server in web applications.
The Web-Portlet module provides the MVC implementation to be used in a portlet environment and mirrors the functionality of Web-Servlet module.
This group comprises of Web, Web-Servlet, Web-Struts and Web-Portlet. These modules provide support to create web application.
These are the design patterns that are used to remove dependency from the programming code. They make the code easier to test and maintain. Let's understand this with the following code:
In such case, there is dependency between the Employee and Address (tight coupling). In the Inversion of Control scenario, we do this something like this:
Thus, IOC makes the code loosely coupled. In such case, there is no need to modify the code if our logic is moved to new environment.
In Spring framework, IOC container is responsible to inject the dependency. We provide metadata to the IOC container either by XML file or annotation.
Advantage of Dependency Injection
- makes the code loosely coupled so easy to maintain
- makes the code easy to test
The Spring web MVC framework provides model-view-controller architecture and ready components that can be used to develop flexible and loosely coupled web applications. The MVC pattern results in separating the different aspects of the application (input logic, business logic, and UI logic), while providing a loose coupling between these elements.
The Model encapsulates the application data and in general they will consist of POJO.
The View is responsible for rendering the model data and in general it generates HTML output that the client's browser can interpret.
The Controller is responsible for processing user requests and building appropriate model and passes it to the view for rendering.
The DispatcherServlet
The Spring Web model-view-controller (MVC) framework is designed around a DispatcherServlet that handles all the HTTP requests and responses. The request processing workflow of the Spring Web MVC DispatcherServlet is illustrated in the following diagram:
Following is the sequence of events corresponding to an incoming HTTP request to DispatcherServlet:
After receiving an HTTP request, DispatcherServlet consults the HandlerMapping to call the appropriate Controller.
The Controller takes the request and calls the appropriate service methods based on used GET or POST method. The service method will set model data based on defined business logic and returns view name to the DispatcherServlet.
The DispatcherServlet will take help from ViewResolver to pickup the defined view for the request.
Once view is finalized, The DispatcherServlet passes the model data to the view which is finally rendered on the browser.
All the above mentioned components ie. HandlerMapping, Controller and ViewResolver are parts of WebApplicationContext which is an extension of the plain ApplicationContext with some extra features necessary for web applications.
Required Configuration
You need to map requests that you want the DispatcherServlet to handle, by using a URL mapping in the web.xml file. The following is an example to show declaration and mapping for HelloWeb DispatcherServlet example:
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>Spring MVC Application</display-name> <servlet> <servlet-name>HelloWeb</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>HelloWeb</servlet-name> <url-pattern>*.jsp</url-pattern> </servlet-mapping> </web-app>
The web.xml file will be kept WebContent/WEB-INF directory of your web application. OK, upon initialization of HelloWeb DispatcherServlet, the framework will try to load the application context from a file named [servlet-name]-servlet.xml located in the application's WebContent/WEB-INF directory. In this case our file will be HelloWeb-servlet.xml.
Next, <servlet-mapping> tag indicates what URLs will be handled by the which DispatcherServlet. Here all the HTTP requests ending with .jsp will be handled by the HelloWeb DispatcherServlet.
If you do not want to go with default filename as [servlet-name]-servlet.xml and default location as WebContent/WEB-INF, you can customize this file name and location by adding the servlet listener ContextLoaderListener in your web.xml file as follows:
<web-app...> <!-------- DispatcherServlet definition goes here-----> .... <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/HelloWeb-servlet.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> </web-app>
Now, let us check the required configuration for HelloWeb-servlet.xml file, placed in your web application's WebContent/WEB-INF directory:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package="com.tutorialspoint" /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean> </beans>
Following are the important points about HelloWeb-servlet.xml file:
The [servlet-name]-servlet.xml file will be used to create the beans defined, overriding the definitions of any beans defined with the same name in the global scope.
The <context:component-scan...> tag will be use to activate Spring MVC annotation scanning capability which allows to make use of annotations like @Controller and @RequestMapping etc.
The InternalResourceViewResolver will have rules defined to resolve the view names. As per the above defined rule, a logical view named hello is delegated to a view implementation located at /WEB-INF/jsp/hello.jsp .
Next section will show you how to create your actual components ie. Controller, Model and View.
Defining a Controller
DispatcherServlet delegates the request to the controllers to execute the functionality specific to it. The @Controller annotation indicates that a particular class serves the role of a controller. The @RequestMapping annotation is used to map a URL to either an entire class or a particular handler method.
@Controller @RequestMapping("/hello") public class HelloController{ @RequestMapping(method = RequestMethod.GET) public String printHello(ModelMap model) { model.addAttribute("message", "Hello Spring MVC Framework!"); return "hello"; } }
The @Controller annotation defines the class as a Spring MVC controller. Here, the first usage of @RequestMapping indicates that all handling methods on this controller are relative to the /hello path. Next annotation @RequestMapping(method = RequestMethod.GET) is used to declare the printHello() method as the controller's default service method to handle HTTP GET request. You can define another method to handle any POST request at the same URL.
You can write above controller in another form where you can add additional attributes in @RequestMapping as follows:
@Controller public class HelloController{ @RequestMapping(value = "/hello", method = RequestMethod.GET) public String printHello(ModelMap model) { model.addAttribute("message", "Hello Spring MVC Framework!"); return "hello"; } }
The value attribute indicates the URL to which the handler method is mapped and the method attribute defines the service method to handle HTTP GET request. There are following important points to be noted about the controller defined above:
You will defined required business logic inside a service method. You can call another methods inside this method as per requirement.
Based on the business logic defined, you will create a model within this method. You can setter different model attributes and these attributes will be accessed by the view to present the final result. This example creates a model with its attribute "message".
A defined service method can return a String which contains the name of the view to be used to render the model. This example returns "hello" as logical view name.
Creating JSP Views
Spring MVC supports many types of views for different presentation technologies. These include - JSPs, HTML, PDF, Excel worksheets, XML, Velocity templates, XSLT, JSON, Atom and RSS feeds, JasperReports etc. But most commonly we use JSP templates written with JSTL. So let us write a simple hello view in /WEB-INF/hello/hello.jsp:
<html> <head> <title>Hello Spring MVC</title> </head> <body> <h2>${message}</h2> </body> </html>
Here ${message} is the attribute which we have setup inside the Controller. You can have multiple attributes to be displayed inside your view.
Steps to create spring application
Here, we are going to learn the simple steps to create the first spring application. To run this application, we are not using any IDE. We are simply using the command prompt. Let's see the simple steps to create the spring application
- create the class
- create the xml file to provide the values
- create the test class
- Load the spring jar files
- Run the test class
1) Create Java class
This is the simple java bean class containing the name property only.
This is simple bean class, containing only one property name with its getters and setters method. This class contains one extra method named displayInfo() that prints the student name by the hello message.
2) Create the xml file
In case of myeclipse IDE, you don't need to create the xml file as myeclipse does this for yourselves. Open the applicationContext.xml file, and write the following code:
The bean element is used to define the bean for the given class. The property subelement of bean specifies the property of the Student class named name. The value specified in the property element will be set in the Student class object by the IOC container.
3) Create the test class
Create the java class e.g. Test. Here we are getting the object of Student class from the IOC container using the getBean() method of BeanFactory. Let's see the code of test class.
The Resource object represents the information of applicationContext.xml file. The Resource is the interface and the ClassPathResource is the implementation class of the Reource interface. The BeanFactory is responsible to return the bean. The XmlBeanFactory is the implementation class of the BeanFactory. There are many methods in the BeanFactory interface. One method is getBean(), which returns the object of the associated class.
4) Load the jar files required for spring framework
There are mainly three jar files required to run this application.
- org.springframework.core-3.0.1.RELEASE-A
- com.springsource.org.apache.commons.logging-1.1.1
- org.springframework.beans-3.0.1.RELEASE-A
For the future use, You can download the required jar files for spring core application.
download the core jar files for spring
To run this example, you need to load only spring core jar files.
5) Run the test class
Now run the Test class. You will get the output Hello: Chandra Vardhan.
No comments:
Post a Comment