You are on page 1of 56

Introduction to the Spring framework

prepared by:

Enabling electronic transactions and bringing information closer to your customers


Module 1
Spring Framework

Objectives
Upon completion of this module, you should be able to:
Describe the seven modules of Spring Framework

Additional Resources
The following references provide additional information on
the topics described in this module:
Naveen Balani, Introduction to the Spring framework A
first look at Spring AOP and the IOC container
[http://www-
128.ibm.com/developerworks/library/wa-spring1/]

2/56`
General Overview

The Spring framework is a layered architecture consisting of seven well-


defined modules. The Spring modules are built on top of the core container,
which defines how beans are created, configured, and managed, as shown in
Figure 1.

Figure 1 The seven modules of the Spring framework

Each of the modules (or components) that comprise the Spring framework
can stand on its own or be implemented jointly with one or more of the others.
The functionality of each component is as follows:

The core container: The core container provides the essential


functionality of the Spring framework. A primary component of the core
container is the BeanFactory, an implementation of the Factory
pattern. The BeanFactory applies the Inversion of Control (IOC)
pattern to separate an application's configuration and dependency
specification from the actual application code.
Spring context: The Spring context is a configuration file that provides
context information to the Spring framework. The Spring context
includes enterprise services such as JNDI, EJB, e-mail, internalization,
validation, and scheduling functionality.
Spring AOP: The Spring AOP module integrates aspect-oriented
programming functionality directly into the Spring framework, through
its configuration management feature. As a result you can easily AOP-
enable any object managed by the Spring framework. The Spring AOP
module provides transaction management services for objects in any

3/56`
Spring-based application. With Spring AOP you can incorporate
declarative transaction management into your applications without
relying on EJB components.
Spring DAO: The Spring JDBC DAO abstraction layer offers a
meaningful exception hierarchy for managing the exception handling
and error messages thrown by different database vendors. The
exception hierarchy simplifies error handling and greatly reduces the
amount of exception code you need to write, such as opening and
closing connections. Spring DAO's JDBC-oriented exceptions comply
to its generic DAO exception hierarchy.
Spring ORM: The Spring framework plugs into several ORM
frameworks to provide its Object Relational tool, including JDO,
Hibernate, and iBatis SQL Maps. All of these comply to Spring's
generic transaction and DAO exception hierarchies.
Spring Web module: The Web context module builds on top of the
application context module, providing contexts for Web-based
applications. As a result, the Spring framework supports integration
with Jakarta Struts. The Web module also eases the tasks of handling
multi-part requests and binding request parameters to domain objects.
Spring MVC framework: The Model-View-Controller (MVC) framework
is a full-featured MVC implementation for building Web applications.
The MVC framework is highly configurable via strategy interfaces and
accommodates numerous view technologies including JSP, Velocity,
Tiles, iText, and POI.

Spring framework functionality can be used in any J2EE server and most of it
also is adaptable to non-managed environments. A central focus of Spring is
to allow for reusable business and data-access objects that are not tied to
specific J2EE services. Such objects can be reused across J2EE
environments (Web or EJB), standalone applications, test environments, and
so on, without any hassle.

The IOC Container


The basic concept of the Inversion of Control pattern is that you do not create
your objects but describe how they should be created. You don't directly
connect your components and services together in code but describe which
services are needed by which components in a configuration file. A container
(in the case of the Spring framework, the IOC container) is then responsible
for hooking it all up.
In a typical IOC scenario, the container creates all the objects, wires them
together by setting the necessary properties, and determines when methods
will be invoked. The three implementation pattern types for IOC are listed in
the table below.

4/56`
Type 1 Services need to implement a dedicated interface through
which they are provided with an object from which they can
look up dependencies (for example, additional needed
services).
Type 2 Dependencies are assigned through JavaBeans properties
(for example, setter methods).
Type 3 Dependencies are provided as constructor parameters and
are not exposed as JavaBeans properties.
The Spring framework uses the Type 2 and Type 3 implementations for its
IOC container.

Aspect-oriented Programming
Aspect-oriented programming, or AOP, is a programming technique that allows
programmers to modularize crosscutting concerns, or behavior that cuts
across the typical divisions of responsibility, such as logging and transaction
management. The core construct of AOP is the aspect, which encapsulates
behaviors affecting multiple classes into reusable modules.

5/56`
Summary

In this first module, we introduced you to the basics of the Spring framework.
We started by discussing the seven modules that comprise Spring's layered
architecture. Soon, we will have a closer look at two of them: The IOC
container and Spring AOP. AOP and IOC are complementary technologies in
that both apply a modular approach to complex problems in enterprise
application development.

Spring does not try to duplicate existing solutions; it tries to integrate with
exiting solutions like JDO, AOP and Hibernate. Spring is portable across
application servers, as it does not include any application server or platform
specific requirements. This makes it compatible on major application servers
like Websphere, Weblogic, Tomcat, Jboss and others like them.

6/56`
Module 2
Spring Core

Objectives
Upon completion of this module, you should be able to:
Understand how Inversion of Control pattern operates
on Spring
Describe the purpose of Inversion of Control pattern

Additional Resources
The following references provide additional information on
the topics described in this module:
Download the Spring framework from the Spring
homepage.
[http://aopalliance.sourceforge.net/]

7/56`
Overview

The core of Spring's design is the org.springframework.beans package,


designed for use with JavaBean components. This package typically isn't
used directly by users, but serves as the underlying medium for much of the
other functionality. The next-highest layer of abstraction is the BeanFactory
interface, an implementation of the Factory design pattern that enables
objects to be created and retrieved by name. BeanFactory can also manage
relationships between objects.

BeanFactory supports two object modes.

Singleton mode provides a shared instance of the object with a


particular name, which will be retrieved on lookup. Singleton is the
default and most often used object mode. It is ideal for stateless
service objects.
Prototype mode ensures that each retrieval will result in the creation of
an independent object. Prototype mode would be best used in a case
where each user needed to have his or her own object.

The bean factory concept is the foundation of Spring as an IOC container.


IOC moves the responsibility for making things happen into the framework
and away from application code. As I'll show in the next examples, the Spring
framework uses JavaBean properties and configuration data to figure out
which dependencies must be set.
The BeanFactory interface

Because org.springframework.beans.factory.BeanFactory is a
simple interface it can be implemented for a range of underlying storage
methods. The most commonly used BeanFactory definition is the
XmlBeanFactory, which loads beans based on definitions in an XML file, as
shown in Listing 2.1.

Listing 2.1. XmlBeanFactory


BeanFactory factory = new XMLBeanFactory(new
FileInputSteam("bean.xml"));

Beans defined in XML files are lazily loaded, which means that the beans
themselves will not be instantiated until they are needed. To retrieve a bean
from BeanFactory you can simply call the getBean() method passing in
the name of the bean you want to retrieve, as shown in Listing 2.2.

Listing 2.2. getBean()


MyBean mybean = (MyBean) factory.getBean("mybean");

8/56`
Each bean definition can be a POJO (defined by class name and JavaBean
initialization properties) or a FactoryBean. The FactoryBean interface
adds a level of indirection to the applications built using the Spring framework.

An IOC example

Now we look at an example that demonstrates how you can inject application
dependencies (rather than build them in) through the Spring IOC container.

We will use the famous Hello World application. With respect to the simple
hello world, our hello world service requires a layout component that will
arrange how the hello world message should be displayed.

The interfaces

As we know the basic concept of the Inversion of Control pattern is that we do


not create our objects but describe how they should be created. This is
achieved by using interfaces, so we will create interfaces for our
HelloWorldService and Layout.

Listing 2.3. HelloWorldService Interface


public interface HelloWorldService {
public String getMessage();
public void setMessage(String message);
public Layout getLayout();
public void setLayout(Layout message);
public void execute();
}

Listing 2.4. Layout Interface


public interface Layout {
public String format( String message );
}

The implementations

We will have one implementation of HelloWorldService and two implementations of


Layout

Listing 2.5. HelloWorldServiceImpl


public class HelloWorldServiceImpl implements HelloWorldService {

private String message;


private Layout layout;

public String getMessage() {


return message;
}

9/56`
public void setMessage(String message) {
this.message = message;
}

public Layout getLayout() {


return layout;
}

public void setLayout(Layout layout) {


this.layout = layout;
}

public void execute() {


System.out.println( getLayout().format ( getMessage() ) );
}
}

Listing 2.6. StandardLayout


public class StandardLayout implements Layout {

public String format(String message) {


return message;
}

Listing 2.7. UppercaseLayout


public class UppercaseLayout implements Layout {

public String format(String message) {


return message.toUpperCase();
}

The application

Our application does not know which implementation it got, it will just use the
interfaces and by the contract everything should work on any
implementations.

10/56`
Listing 2.8. HelloWorldApp

public class HelloWorldApp {

/**
* @param args
*/
public static void main(String[] args) {

try {
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {
"config/bean.xml"
});
HelloWorldService helloWorldService =
(HelloWorldService)
context.getBean("helloWorldService");
helloWorldService.execute();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}

Spring keeps it loose

With all the interfaces and implementations in place, the next thing to consider
is how to integrate them in a loosely coupled manner. In Listing 2.8 you can
see how we configure this

Listing 2.8. bean.xml


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="helloWorldService"
class="examples.spring.HelloWorldServiceImpl">
<property name="message">
<value>Hello World</value>
</property>
<property name="layout">
<ref bean="standardLayout"/>
</property>
</bean>
<bean id="standardLayout"
class="examples.spring.StandardLayout">
</bean>
<bean id="uppercaseLayout"
class="examples.spring.UppercaseLayout">
</bean>
</beans>

11/56`
The Bean Configuration file tells Spring:
- Bean id is helloWorldService (The name of the Bean)
With Class HelloWorldServiceImpl (What class to load dynamically)
Property Message with Value=Hello World
Property Layout with value refers to bean with id StandardLayout
- Bean id is standardLayout (The name of the Bean)
With Class StandardLayout
- Bean id is uppercaseLayout (The name of the Bean)
With Class UppercaseLayout

Note that all the setter methods are implemented by Spring configuration
beans. All the dependencies (that is, the message and the layout interface)
can be injected by the Spring framework using these beans. The execute()
method will then use them to carry out the remainder of the implementation.

12/56`
Creating the projects

To run example above we will use Eclipse, Maven, and Maven plugin to
create our SpringHello project.

13/56`
Then add dependency to Spring Framework

14/56`
Now create the interfaces and classes from above listings into appropriate
packages (say, examples.spring)

15/56`
Create the bean.xml file in resources folder:

Spring depends on log4j. Create a log4j.properties file in the


src/main/resources folder and add the code in Listing 2.9 to have a
debugging output to the console.

16/56`
Listing 2.9. log4j.properties

### direct log messages to stdout ###


log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p
%c{1}:%L - %m%n

log4j.rootLogger=error, stdout

17/56`
Now, we can run the HelloWorldApp

Try to change the layout properties from StandardLayout to UppercaseLayout


on bean.xml and rerun the application and see what happens.

18/56`
Summary
Since learning is best accomplished by doing, we used a working example to
show you how the IOC pattern (as implemented by the Spring IOC container)
works to integrate disparate systems in a loosely coupled manner. In this
example you saw how simple it was to inject dependencies, or services, than
having to build them in from the ground up.

19/56`
Module 3
Spring AOP

Objectives
Upon completion of this module, you should be able to:
Describe the concept of aspect, advice, joinpoint,
pointcut, and target
Describe the purpose of Aspect Oriented
Programming

Additional Resources
The following references provide additional information
on the topics described in this module:
R.J. Lorimer , Spring: A Quick Journey Through
Spring AOP
[http://www.javalobby.org/java/forums/t44746.ht
ml]

Spring AOP isn't the only AOP implementation,


although it does offer distinct advantages. Read
"AOP tools comparison, Part 1" (developerWorks,
February 2005) to find out how Spring AOP stacks
up.
[http://www.ibm.com/developerworks/java/library
/j-aopwork1/]

Learn how to develop a transactional persistence


layer using Hibernate and Spring AOP with "Object-
relation mapping without the container"
(developerWorks, April 2004).
[http://www.ibm.com/developerworks/java/
library/j-hibern/]

20/56`
Overview

One of the strengths of the Spring Framework is its robust and flexible aspect
oriented programming infrastructure. In Spring, AOP is a little different than
other AOP frameworks in that it brings with it a consistent AOP infrastructure
that can be applied for other AOP technical solutions.

Spring's 'built-in' AOP infrastructure is defined by the


org.springframework.aop.* packages. To understand the packages, you
have to have at least some idea of the concepts of AOP as Spring models
these concepts *very* closely in implementation, so we'll explain them.

Aspect - Think of this as the general feature you want to apply globally
to your application (logging, performance monitoring, exception
handling, transaction management, etc).

Advice - A chunk of code that is invoked during program execution,


and is a piece of the logic for implementing your aspect. This is the first
important piece of a Spring AOP aspect implementation!

Joinpoint - A *single* location in the code where an advice should be


executed (such as field access, method invocation, constructor
invocation, etc.). Spring's built-in AOP only supports method invocation
currently, so joinpoints aren't particularly important to focus on at this
point.

Pointcut - A pointcut is a set of many joinpoints where an advice


should be executed. So if, in Spring, a joinpoint is always a method
invocation, then a pointcut is just a set of methods that, when called,
should have advices invoked around them. This is the second
important pieces of a Spring AOP aspect implementation!

Targets/Target Objects - The objects you want to apply an aspect or


set of aspects to!

Introduction - This is the ability to add methods to an object. This is


closely tied to, and is almost analogous to the term 'mixins'. It's really
just a way to make an object of type A also an object of type B.
Introduction in Spring is limited to interfaces.

21/56`
Spring and Advice Objects

We start with the concept of advice objects, because they are the easiest to
bridge to from a non-AOP way of thinking. Advice implementations in Spring
are simply implementations of the
org.aopalliance.intercept.MethodInterceptor interface. That's not a
Spring class! So it turns out that Spring's AOP implementation uses a
*standard* AOP API from the AOP Alliance, which you can read more about it
on http://aopalliance.sourceforge.net/. The MethodInterceptor interface is
actually a child of the org.aopalliance.intercept.Interceptor interface,
which is a child of another interface, org.aopalliance.aop.Advice.
Remember that Spring AOP only supports method invocation, but that
conceptually, an advice could include field access, constructor invocation and
a bunch of other things. That is why Spring's advice starts at the
MethodInterceptor interface, even though there are other interfaces higher
up - because MethodInterceptor is the sub-interface that is designed for
method-invocation style advice and for which Spring has support. The
MethodInterceptor interface is really quite simple:

Listing 3.1. MethodInterceptor


public interface MethodInterceptor extends Interceptor {

Object invoke(MethodInvocation invocation) throws Throwable;

Basically, when you write an advice for intercepting a method, you have to
implement one method - the invoke method, and you are given a
MethodInvocation object to work with. The MethodInvocation object tells us
a bunch of stuff about the method that we're intercepting, and also gives a
hook to tell the method to go ahead and run.

Let's jump right in and look at a (very) basic method performance profiling
advice:

Listing 3.2. PerformanceInterceptor


import org.aopalliance.intercept.*;

public class PerformanceInterceptor implements MethodInterceptor {

public Object invoke(MethodInvocation method) throws Throwable {


long start = System.currentTimeMillis();
try {
Object result = method.proceed();
return result;
}
22/56`
finally {
long end = System.currentTimeMillis();
long timeMs = end - start;
System.out.println(
"Method: " + method.toString() +
" took: " + timeMs +"ms."
);
}
}
}

Not too complicated really - just capture the time before the method
invocation, tell the method to go ahead and run, then afterward capture the
time again, calculate the difference, and print it out. Incidentally, Spring
already has a better implementation of this type of interceptor - the
org.springframework.aop.interceptor.PerformanceMonitorInterceptor -
there are actually quite a few useful concrete interceptor implementations in
there - check it out.

Spring has multiple alternatives to the basic MethodInterceptor , however,


(which is referred to in the Spring documentation as an 'around' advice) so
that if you want to do more specific things, you can with less complication -
these extensions come in the form of Spring-specific extensions to the Advice
interface (siblings to the MethodInterceptor interface), and they include:

org.springframework.aop.MethodBeforeAdvice - Implementations
of this interface have to implement this contract:

void before(Method method, Object[] args, Object target) throws


Throwable;

You'll notice in this case you aren't given the MethodInvocation object, just
the underlying Method object - this is because the call to proceed() will be
handled by Spring for you; all you need to do is do what you need *before* the
method is called (as the interface name implies).

org.springframework.aop.AfterReturningAdvice - This is the pong


to the ping of MethodBeforeAdvice .
This interface's method will be called on the return from the invocation
of a method. The contract looks like this:

void afterReturning(Object returnValue, Method method, Object[]


args, Object target) throws Throwable;

You'll notice it looks a whole like the before advice, but simply adds the
Object's return value to the method arguments.

org.springframework.aop.ThrowsAdvice - This is a strange


implementation. Instead of requiring you to implement a particular

23/56`
contract, this is simply a 'marker' interface, and expects you to
implement any number of methods that look like this:

void afterThrowing([Method], [args], [target], [some type of


throwable] subclass)

Oddly enough, the only mandatory argument is the Throwable sub-


type.

Here is a snapshot that generally covers the 'advice' hierarchy:

That's a primer on advice objects. Not too bad so far, right? If you've ever
worked with in reflection in Java, most of this is fairly similar in style.

Spring and Pointcuts

What separates AOP from object-oriented design patterns such as the


decorator pattern, at least when talking about Spring AOP, is the fact that the
*what* is defined seperately from the *where* (or would it be *whom*?). In
other words, the 'advice', which is the code to be invoked, is disconnected
entirely from the particular item it is 'advising' - which, again, in the Spring
case is always a method. In other words, an advice in Spring doesn't have
any association, type binding, dependency, or any other form of direct
awareness of the method it is working with.

Remember that the thing that an advice works with is called a JoinPoint. Our
join points in Spring are always methods, and at runtime resolve to
org.aopalliance.aop.Method objects which have made appearances as
method arguments to our advices above. To solidify the point,
org.aopalliance.aop.Method extends org.aopalliance.aop.JoinPoint .

The reason we are bringing joinpoints back up is because a Pointcut object


is all about defining all of the joinpoints that an advice should be 'applied to'.
24/56`
In Spring terms, a pointcut defines all of the methods that our interceptor
should intercept. Pointcuts in Spring implement the
org.springframework.aop.Pointcut interface and look something like this:

Listing 3.3. PointCut Interface


public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
}

The class filter is a special type of object that describes which classes have
potential joinpoints (read methods) on them. The method matcher simply
describes which methods for a given class are considered valid joinpoints for
this pointcut. We don't want to spend too much time on the pointcut interface,
however, because chances are - you won't be implementing it.

Static vs. Dynamic Method Matching

Spring makes a distinction between static and dynamic method matching. A


static method matching pointcut (a subclass of the
org.springframework.aop.support.StaticMethodMatcherPointcut class)
knows at the time it proxies a target object what methods it considers
joinpoints on that object. A dymamic method matching pointcut (see below for
implementation details), on the other hand must be consulted at *every*
method invocation. This is a useful implementation detail because a static
method matcher, while having less flexibility (you can't check the method
invocation arguments), is, by design, much faster, as the check is only
performed once, rather than at every method invocation. Static Matching
pointcuts implementations look something like this:

Listing 3.4. MyBeanStaticPointCut

public class MyBeanStaticPointcut extends


StaticMethodMatcherPointcut {
public boolean matches(java.lang.reflect.Method theMethod,
java.lang.Class theClass, Object[] arguments) {
return
(MyBean.class.isAssignableFrom(theClass) &&
theMethod.equals(...));
}
}

In most cases, however, this is irrelevant, because there is a very convenient


pair of static method matchers that cover almost all concerns - the
org.springframework.aop.support.JdkRegexpMethodPointcut and
org.springframework.aop.support.PerlRegexpMethodPointcut classes. You
25/56`
typically configure these outside of your code (we'll get to configuration in a
bit), and don't have to do any nasty reflection checks as seen above. In
addition, there is a simpler variety of text-based matching called the
NameMatchedMethodPointcut - which is similar to the regex implementations,
but only matches exact names.

Dynamic matching pointcut implementations typically look something like this:

Listing 3.5. MyBeanDynamicPointcut


public class MyBeanDynamicPointcut extends
DynamicMethodMatcherPointCut {
public boolean matches(java.lang.reflect.Method theMethod,
java.lang.Class theClass) {
boolean matches = false;
if(MyBean.class.isAssignableFrom(theClass) &&
theMethod.equals(...)) {
if(arguments[0].equals("Joe Smith")) {
matches = true;
}
}
return matches;
}
}

Due to the nature of dynamic pointcuts, there are no real convenience


implementations of this class. Here is what the pointcut hierarchy generally
looks like:

You may have noticed, neither of above pointcut examples made any
reference to any advice (e.g. MethodInterceptor implementation) - remember
that an advice knows the *what*, not the *where*? Well, a pointcut is the
inverse - it knows the *where*, not the *what*. Therefore, theoretically, these
two components can be intermingled in different configurations and reused.

Tying Pointcuts with Advisors - PointcutAdvisors

Weve gone to great lengths above to clarify that pointcuts don't know about
advice objects, and advice objects don't know about pointcuts. Some object
somewhere, however, must know about both if we are going to have any hope
26/56`
of wrapping our beans in aspects. That is where implementations of
PointcutAdvisor come in. Conceptually speaking, a PointcutAdvisor is
nothing more than a pointcut and an advice object combined - hence the
name. The most basic variety of pointcut advisor is the
org.springframework.aop.support.DefaultPointcutAdvisor class. This is
for the most part just a bean that has two references - something akin to this:

Listing 3.6. DefaultPointcutAdvisor


public class DefaultPointcutAdvisor {
private Pointcut pointcut;
private Advice advice;

public Pointcut getPointcut() { return pointcut; }


public Advice getAdvice() { return advice; }
public void setPointcut(Pointcut pc) { pointcut = pc; }
public void setAdvice(Advice a) { advice = a; }

Yes, yes, in reality it is more complicated than this - but really that is the bulk
of it right there. Now we are getting to a point where we can define the *what*
(the Advice) and the *where* (the Pointcut) in one discrete location. A basic
configuration of this advisor in a spring bean definition may look something
like this:

Listing 3.7. Basic Spring configuration file for pointcut advisor


<!--
A simple name matching pointcut that will consider all methods named
'execute'
as joinpoints
-->
<bean name="controller.handle.pointcut"
class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedName" value="execute"/>
</bean>

<!-- A simple MethodInterceptor style advice object (InterceptorA


implements MethodInterceptor) -->
<bean name="interceptorA" class="examples.spring.InterceptorA" />
<!-- A simple MethodBeforeAdvice style advice object (BeforeAdviceA
implements MethodBeforeAdvice) -->
<bean name="beforeAdviceA" class="examples.spring.BeforeAdviceA"/>

<!-- A pointcut advisor that combines the controller pointcut with


interceptor A -->
<bean name="pointcut.advisor1"
class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="interceptorA"/>
<property name="pointcut" ref="controller.handle.pointcut"/>
</bean>

27/56`
<!--
An alternative pointcut advisor that combines the before advice with
the controller pointcut
Showing how reuse of pointcuts and advices is possible
-->
<bean name="pointcut.advisor2"
class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="beforeAdviceA"/>
<property name="pointcut" ref="controller.handle.pointcut"/>
</bean>

Hopefully this gives you some idea of the relationship of these three classes.
As you can see, advice objects and pointcuts can be intermixed freely into
varying pointcut advisors.

Let's Simplify Things

Ok, now, throw all of that example out of the window. Why? Well, because in
reality while the above example is much more flexible, it is quite verbose as
well. Most times that level of granularity is unnecessary, as we will soon see.
Earlier I glossed over the
org.springframework.aop.support.PointcutAdvisor class hierarchy, and
just mentioned the most basic DefaultPointcutAdvisor . Let's take a closer
look at the available class hierarchy now:

Did you notice how similar the names are to the pointcuts we just learned
about? Most of these classes take the separation of pointcut and advisor out
of the equation, which, while theoretically reducing some degree of flexibility,
typically makes configuration much easier. Here is the same example above,
using the NameMatchMethodPointcut Advisor object (which combines the
PointcutAdvisor API with the NameMatchMethodPointcut class):

Listing 3.8. Spring configuration file using NameMatchMethodPointcut Advisor


<!-- A simple MethodInterceptor style advice object (InterceptorA
implements MethodInterceptor) -->

<bean name="interceptorA" class="examples.spring.InterceptorA" />


<!-- A simple MethodBeforeAdvice style advice object (BeforeAdviceA
implements MethodBeforeAdvice) -->
28/56`
<bean name="beforeAdviceA" class="examples.spring.BeforeAdviceA"/>

<!--
Use the NameMatchMethod pointcut advisor to make things a little
simpler.
-->
<bean name="pointcut.advisor1"
class="org.springframework.aop.support.NameMatchMethodPointcutAdviso
r">
<property name="advice" ref="interceptorA"/>
<property name="mappedName" value="execute"/>
</bean>
<!--
Use the NameMatchMethod pointcut advisor to make things a little
simpler.
-->
<bean name="pointcut.advisor2"
class="org.springframework.aop.support.NameMatchMethodPointcutAdviso
r">
<property name="advice" ref="beforeAdviceA"/>
<property name="mappedName" value="execute"/>
</bean>

As you can see, we got rid of the configuration of one bean entirely.
Technically speaking we are no longer reusing the pointcut, but since pointcut
definitions are typically a configuration concern (as seen above), it doesn't
usually matter one way or another to us.

Gluing Advice & Pointcut All Together

So, we've covered advice objects and pointcut objects - which when you get
down to it, are the core; the center of Spring AOP support. Then we covered
pointcut advisors which take advice objects and pointcut objects and glue
them together into one cohesive chunk - the peanut butter and jelly; the meat
and potatoes; the spaghetti and meatballs; the lamb and tunafish. There is a
very important piece of the puzzle missing however: how do we wrap these
pointcut-advisor combos around our objects? After all, that is the whole point
of all of this. Enter the ProxyFactoryBean .

Without getting into too much detail, Spring supports the concept of a
FactoryBean , which is a special type of bean, in that the bean returned is a
factory result, rather than just a plain 'newInstance()' call on the class you
provided. So, you could have a factory bean implementation that, based on
certain configuration details, factoried different implementations of a certain
class. So, just to solidify the point, in this example:

Listing 3.9. Configuration of myBean


<bean name="myBean" class="examples.spring.MyFactoryBean"/>

29/56`
If you ask for myBean from the bean factory, you're *not* going to get an
instance of MyFactoryBean - instead, Spring is going to consult with the
MyFactoryBean object, and ask it to provide the object you want.

Why is all of this important? Well, because this FactoryBean concept is how
Spring wraps your beans - via the some configuration details, and then using
some internal tool (dynamic proxies, CGLib, etc.) to create a proxy for your
bean that executes some advice on method calls when the pointcut says the
method is a joinpoint (assuming a pointcut is defined).

Expanding our example above, here is how Spring's proxy factory bean
works:

Listing 3.10. Configuration of ProxyFactoryBean

<!-- A simple MethodInterceptor style advice object (InterceptorA


implements MethodInterceptor) -->
<bean name="interceptorA" class="examples.spring.InterceptorA" />
<!-- A simple MethodBeforeAdvice style advice object (BeforeAdviceA
implements MethodBeforeAdvice) -->
<bean name="beforeAdviceA" class="examples.spring.BeforeAdviceA"/>

<!--
Use the NameMatchMethod pointcut advisor to make things a little
simpler.
-->
<bean name="pointcut.advisor1"
class="org.springframework.aop.support.NameMatchMethodPointcutAdviso
r">
<property name="advice" ref="interceptorA"/>
<property name="mappedName" value="execute"/>
</bean>

<!--
Use the NameMatchMethod pointcut advisor to make things a little
simpler.
-->
<bean name="pointcut.advisor2"
class="org.springframework.aop.support.NameMatchMethodPointcutAdviso
r">
<property name="advice" ref="beforeAdviceA"/>
<property name="mappedName" value="execute"/>
</bean>

<!-- Create our controller bean -->


<bean name="myRawController"
class="examples.spring.ExampleController" />

<!-- Create the proxy bean that returns AOP'd varieties of our
controller -->
<bean name="myController"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces"><value> aop.IController
</value></property>
<property name="interceptorNames">
30/56`
<list>
<value>pointcut.advisor2</value>
<value>pointcut.advisor1</value>
<value>myRawController</value>
</list>
</property>
</bean>

Notice the interceptorNames property? This is how we tell the proxy factory
bean what advisors or advice objects we want to apply to the proxied bean.
Order is important in this list - the order the advisors or advice objects are
entered in the list defines the order they will be invoked when entering and
exiting the bean. Note that in this case the *last* entry in the list is our bean
that we want to be proxied. This is just one possible way to define the bean to
be proxied as we'll see in a moment. Also, did you notice that we said
advisors or advice objects ? That is because the proxy factory bean allows
for another shortcut; not specifying a pointcut at all, just an advice. In those
cases, an 'every method is a joinpoint' style pointcut will automatically be
applied. So, if we didn't care which methods were advised, we could shorten
the example above like this:

Listing 3.11. Every Method Pointcut Configuration file


<!-- A simple MethodInterceptor style advice object (InterceptorA
implements MethodInterceptor) -->
<bean name="interceptorA" class="examples.spring.InterceptorA" />
<!-- A simple MethodBeforeAdvice style advice object (BeforeAdviceA
implements MethodBeforeAdvice) -->
<bean name="beforeAdviceA" class="examples.spring.BeforeAdviceA"/>

<!-- Create our controller bean -->


<bean name="myRawController"
class="examples.spring.ExampleController" />

<!-- Create the proxy bean that returns AOP'd varieties of our
controller -->
<bean name="myController"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces"><value>
aop.Icontroller</value></property>
<property name="interceptorNames">
<list>
<value>beforeAdviceA</value>
<value>interceptorA</value>
<value>myRawController</value>
</list>
</property>
</bean>

Now, I mentioned earlier that there is another way to specify the target bean.
This can be done through the targetName and/or target properties on the
factory bean:
31/56`
Listing 3.10. Alternative style for defining target

<!-- Create the proxy bean that returns AOP'd varieties of our
controller -->
<bean name="myController"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces"><value>
aop.Icontroller</value></property>
<property name="target" ref="myRawController"/>
<property name="interceptorNames">
<list>
<value>beforeAdviceA</value>
<value>interceptorA</value>
</list>
</property>
</bean>

If you don't need direct (non-AOP'd) access to your bean, then it may be
better for the simplicity of the file to just use an anonymous inner bean, rather
than declaring the bean separately to the proxy:

Listing 3.12. Alternative style for defining target within


ProxyFactoryBean

<!-- Create the proxy bean that returns AOP'd varieties of our
controller -->
<bean name="myController"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property
name="proxyInterfaces"><value>aop.Icontroller</value></property>
<property name="target"><bean class="
examples.spring.ExampleController"/></property>
<property name="interceptorNames">
<list>
<value>beforeAdviceA</value>
<value>interceptorA</value>
</list>
</property>
</bean>

32/56`
See AOP in action

To complete our learning now lets how to configure PerformanceInterceptor


to our HelloWorldService example by adding Listing 3.13 to our bean.xml.

Listing 3.13. Configuring PerformanceInterceptor to HelloWorldService


<bean name="performanceInterceptor"
class="examples.spring.PerformanceInterceptor" />

<bean name="pointcut.advisor"
class="org.springframework.aop.support.NameMatchMethodPointcutAdvis
or">
<property name="advice" ref="performanceInterceptor"/>
<property name="mappedName" value="execute"/>
</bean>

<bean name="helloWorldProxy"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property
name="proxyInterfaces"><value>examples.spring.HelloWorldService</va
lue></property>
<property name="interceptorNames">
<list>
<value>pointcut.advisor</value>
<value>helloWorldService</value>
</list>
</property>
</bean>

And change one line of HelloWorldApp to call our helloWorldProxy instead of


plain helloWorldService bean.

Listing 3.13. Configuring PerformanceInterceptor to HelloWorldService


HelloWorldService helloWorldService = (HelloWorldService)
context.getBean("helloWorldProxy");

33/56`
34/56`
Summary

We have gone through some basic concepts on Spring AOP. In a typical


object-oriented development approach you might implement logging
functionality by putting logger statements in all your methods and Java
classes. In an AOP approach you would instead modularize the logging
services and apply them declaratively to the components that required
logging. The advantage, of course, is that the Java class doesn't need to
know about the existence of the logging service or concern itself with any
related code. As a result, application code written using Spring AOP is loosely
coupled.

There are more topics on Spring AOP that were not covered in this module,
such as:

Introductions/Mixins
Specialized Proxy Support (such as the TransactionProxyFactoryBean)
Other corner cases

35/56`
Module 4
Spring DAO

Objectives
Upon completion of this module, you should be able to:
Understand how Spring DAO works
Use Spring DAO library to simplify data access

Additional Resources
The following references provide additional information on
the topics described in this module:
Sebastian Hennebrueder, Spring DAO with JDBC
[http://www.laliluna.de/download/eclipse-spring-
jdbctutorial-en.pdf]

36/56`
Overview

In this module we will explains how to implement the design pattern Data
Access Objects (DAO) to access a Database with JDBC in Spring.

Integration of JDBC, Hibernate, JDO, EJB to access databases

Spring allows to integrate any of above solutions to access our database. The
interface is well designed and lets us easily replace a JDBC database access
with a Hibernate based database access.

Hibernate, JDO and EJB are solutions to map database data to classes, e.g.
Reading a line of the table book and writing it to a object of class type book.
This allows you to use classes instead of result sets in your application and is
considered as good design, because your application keeps being object
oriented.

If you use JDBC access, Spring provides an abstract exception layer. If you
change your database from Sybase to Oracle you do not have to change the
exception handling from SybaseDataAcception to OracleDataException.
Spring catches the application server specific Exception and throws a Spring
dataexception.

Before we start the project, we will need

JDBC Driver our database. In this example we use Oracle database,


so we will use JDBC Oracle driver
The database and tables

Listing 4.1. Create Table Book


CREATE TABLE book
(
id number(8),
title varchar2(60),
author varchar2(40),
borrowed_by varchar2(40),
primary key (id)
);

37/56`
The domain classes

The domain classes is class book which is a normal Java bean with private
attributes and public getter/setter and constructor method.

38/56`
Listing 4.2. Book
public class Book {
// unique number to indentify the book
private Integer id;

// the title
private String title;

// the authors name


private String author;

// null or the id of the client who borrowed the book


private Integer borrowedBy;

public Book() {
}

public Book(Integer id, String title, String author, Integer


borrowedBy) {
this.setId(id);
this.setTitle(title);
this.setAuthor(author);
this.setBorrowedBy(borrowedBy);
}

public String getAuthor() {


return author;
}

public void setAuthor(String author) {


this.author = author;
}

public Integer getBorrowedBy() {


return borrowedBy;
}

public void setBorrowedBy(Integer borrowedBy) {


this.borrowedBy = borrowedBy;
}

public Integer getId() {


return id;
}

public void setId(Integer id) {


this.id = id;
}

public String getTitle() {


return title;
}

public void setTitle(String title) {


this.title = title;
}
}
39/56`
40/56`
The DAO

We define the interface and implementation for our DAO below

Listing 4.3. LibraryDao Interface


public interface LibraryDao {
/**
* gets id generated from db and insert book in database
* @param book
* @return book with new generated id
*/
public abstract Book insertBook(Book book);
/**
* updates the book in the database
* @param book
*/
public abstract int updateBook(Book book);
/**
* deletes book in the database
* @param book
*/
public abstract int deleteBook(Book book);
/**
* loads all books from the database and puts them in a
java.util.List
* @return list of books
*/
public abstract List<Book> getBooks();
}

Now create a new class LibraryDaoImpl with superclass is JdbcDaoSupport


and add the interface you just created to the interface list. Make sure to check
the options to generate abstract methods and comments.

Listing 4.4. LibraryDaoImpl

public class LibraryDaoImpl extends JdbcDaoSupport implements


LibraryDao {

private DataFieldMaxValueIncrementer bookIncrementer;


private static final String SQL_INSERT =
"insert into book (id, title, author) values (?,?,?)";
private static final String SQL_UPDATE =
"update book set title=?, author=?, borrowedby=? where id = ?
";
private static final String SQL_DELETE =
"delete from book where id = ?";
private static final String SQL_SELECT =
"select * from book";

private QueryInsert queryInsert;


private QueryUpdate queryUpdate;
private QueryDelete queryDelete;
private QuerySelect querySelect;

41/56`
public void setBookIncrementer(DataFieldMaxValueIncrementer
bookIncrementer) {
this.bookIncrementer = bookIncrementer;
}
..........................

We use JdbcDaoSupport to access the database. This JdbcDaoSupport will


keeps us away from dealing with JDBC datasources and connections.

We also define the SQL statements as constants, and some query attributes
that are instances of these private Class.

Listing 4.5. Private Classes within LibraryDaoImpl


class QueryInsert extends SqlUpdate {
public QueryInsert( DataSource ds ) {
super(ds, SQL_INSERT );
declareParameter(new SqlParameter(Types.NUMERIC)); // id
declareParameter(new SqlParameter(Types.VARCHAR)); // title
declareParameter(new SqlParameter(Types.VARCHAR)); // author
compile();
}
}

class QueryUpdate extends SqlUpdate {


public QueryUpdate( DataSource ds ) {
super(ds, SQL_UPDATE );
declareParameter(new SqlParameter(Types.VARCHAR)); // title
declareParameter(new SqlParameter(Types.VARCHAR)); // author
declareParameter(new SqlParameter(Types.VARCHAR));
//borrowedBy
declareParameter(new SqlParameter(Types.NUMERIC)); // id
compile();
}
}

class QueryDelete extends SqlUpdate {


public QueryDelete( DataSource ds ) {
super(ds, SQL_DELETE );
declareParameter(new SqlParameter(Types.NUMERIC));//id
compile();
}
}

class QuerySelect extends MappingSqlQuery {


public QuerySelect ( DataSource ds ) {
super(ds, SQL_SELECT );
compile();
}
@Override
protected Object mapRow(ResultSet rs, int rowNum)
throws SQLException {
Book book = new new Book(
rs.getInt("id"),
rs.getString("title"),

42/56`
rs.getString("author"),
rs.getInt("borrowed_by"));
return book;
}
}

Each query is defined as private class. It will needs the sql and declarations of
parameters types, showing which kind of parameters we are passing.

You need not to pass the types but may have Spring to find out which types
are passed. But this can be a problem when passing null values. So just don't
do it. We will use book objects anywhere so when we read data from the
database we will have to map the resultset of a query to the class.

Notice that for insert, update and delete query, we extend our private class
from SqlUpdate class and for select query, we extend it from
MappingSqlQuery.

Both SqlUpdate and MappingSqlQuery provides a convenient method to


access data, and to read data we need to override the mapRow method.

We also need to override the initDao method and instantiate our private query
attributes from our private classes appropriately. We will configure the
datasource later.

Listing 4.6. initDao method

@Override
protected void initDao() throws Exception {
super.initDao();
this.queryInsert = new QueryInsert( getDataSource() );
this.queryUpdate = new QueryUpdate( getDataSource() );
this.queryDelete = new QueryDelete( getDataSource() );
this.querySelect = new QuerySelect( getDataSource() );
}

And now, for insert, update and delete method, we need no further
preparation, so have a look at the source code below:

Listing 4.7. Query Methods


public Book insertBook(Book book) {
Integer id = bookIncrementer.nextIntValue();
book.setId ( id );
Object values[] = new Object[] {
book.getId(),
book.getTitle(),
book.getAuthor()
};
queryInsert.update ( values );
return book;
}

43/56`
public int updateBook(Book book) {
Object values[] = new Object[] {
book.getTitle(),
book.getAuthor(),
book.getBorrowedBy(),
book.getId()
};
return queryUpdate.update(values);
}

public int deleteBook(Book book) {


return queryDelete.update(book.getId());
}

public List<Book> getBooks() {


return (List<Book) querySelect.execute();
}

It is really simple isn't it. Imagine if you would have to create a connection for
each access of the database, close it and handle all the possible exceptions.

Now, we create a test class for out DAO.

Listing 4.8. TestClient


public class TestClient {
/**
* @param args
*/
public static void main(String[] args) {
TestClient testClient = new TestClient();
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {
"config/bean.xml"
});
LibraryDao libraryDao = (LibraryDao)
context.getBean("libraryDao");

testClient.testInsertUpdateDelete(libraryDao);
}

private void testInsertUpdateDelete(LibraryDao libraryDao) {


// insert a book
Book book = libraryDao.insertBook(new Book(null,
"My life as Java bean", "Sebastian", null));
System.out.println("List books:");
List famousBooks = libraryDao.getBooks();
for (Iterator iter = famousBooks.iterator(); iter.hasNext();)
{
Book element = (Book) iter.next();
System.out.println("Book: " + element.getTitle() +
" written by "
+ element.getAuthor());
}
// update a book
book.setTitle("My life as Java bean, edition 2");

44/56`
libraryDao.updateBook(book);
System.out.println("List books:");
famousBooks = libraryDao.getBooks();
for (Iterator iter = famousBooks.iterator(); iter.hasNext();)
{
Book element = (Book) iter.next();
System.out.println("Book: " + element.getTitle() +
" written by "
+ element.getAuthor());
}
// delete the book
libraryDao.deleteBook(book);
System.out.println("List books:");
famousBooks = libraryDao.getBooks();
for (Iterator iter = famousBooks.iterator(); iter.hasNext();)
{
Book element = (Book) iter.next();
System.out.println("Book: " + element.getTitle() +
" written by "
+ element.getAuthor());
}
}

In our sourcecode we used a DataFieldMaxValueIncrementer and a


DataSource but where does this come from? We could of course create this in
our application, but we will configure this in a spring configuration file and
using IOC approach.

45/56`
Listing 4.9. bean.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="libraryDao" class="examples.spring.LibraryDaoImpl"
singleton="true">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="bookIncrementer">
<ref bean="bookIncrementer" />
</property>
</bean>

<bean id="bookIncrementer"

class="org.springframework.jdbc.support.incrementer.OracleSequenceM
axValueIncrementer">
<constructor-arg>
<ref bean="dataSource" />
</constructor-arg>
<constructor-arg>
<value>book_id_seq</value>
</constructor-arg>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
>
<property name="driverClassName"
value="oracle.jdbc.driver.OracleDriver" />
<property name="url"
value="jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTO
COL=TCP)(HOST=10.8.9.101)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=x
e)(SERVER=DEDICATED)))" />
<property name="username" value="bvk" />
<property name="password" value="bvk" />
</bean>

</beans>

46/56`
Summary

We have brief you step by step on how to use Spring DAO, the following
topics can be found out by yourself:

Replacing the datasource with a connection pool


The use of a simple datasource is not adequate for larger applications.
Spring provides adapters to connection pools like dbcp or pools coming
from JNDI contexts. The latter is provided by Tomcat, JBoss,
Websphere etc.
Object Relational Mapping
We could replace the JDBC access with a Object relational mapping
solution like Hibernate, because Hibernate provides already all we
have just created by hand and even more.
Adding transactions to our application
Once we add business methods dealing with multiple queries in the
same business process, we will have to use transactions. Spring
provides adapters so that we could use the transaction manager from
J2EE solutions or transactions as provided from the database.

47/56`
Module 5
Using OpenSymphony Quartz Scheduler in Spring

Objectives
Upon completion of this module, you should be able to:
Describe the seven modules of Spring Framework

Additional Resources
The following references provide additional information on
the topics described in this module:
Christophe Verr, Using OpenSymphony Quartz
Scheduler in Spring
[http://www.javaranch.com/journal/
200711/combining_spring_and_quartz.html]

Quartz Home Page


[http://www.opensymphony.com/quartz/]

48/56`
Overview

Often our application need to run task regularly, Spring offers a few helper
classes to do some scheduling in our application. In Spring 2.0, both the
JDK's Timer objects and the OpenSymphony Quartz Scheduler are
supported. Quartz is an open source job scheduling system that can be easily
used with Spring.

About Quartz
Quartz offers five main structures to realize scheduling:
The Job interface
The JobDetail class
The Trigger abstract class
The Scheduler interface
The SchedulerFactory interface

The Job interface represents a job. A job does something, only one thing. Its
API is very straightforward. Only one execute() method, which will be called
by Quartz when a Job has to be executed. Some useful information can be
retrieved from the JobExecutionContext that is passed to the execute()
method.

Listing 5.1. Job Interface


public interface Job {
void execute (JobExecutionContext ctx);
}

Some data can be passed to jobs via the JobDataMap class. If a JobDataMap
is registered in a JobDetail, it can be accessed from the Job, via the
JobExecutionContext which is passed to the execute() method of the Job
interface. The JobDetail class is used to give some information about a
particular Job. Jobs are started (or "fired") by triggers, which are represented
by the Trigger class. Quartz has some convenient implementation class of
Trigger, such as SimpleTrigger and CronTrigger. A SimpleTrigger acts like a
basic timer, where you can define a starting time, an ending time, a repeat
count and a repeat interval. A CronTrigger uses more advanced settings,
using the "cron" Unix utility notation. The settings for a CronTrigger can be
very specific, like "fire the job at 10:15am on every last Friday of every month
during the years 2008, 2009, 2010". One notion is that jobs and triggers are
given names, and may be assigned to a group. A name must be unique within
the same group. So you can create a trigger for one group, and all jobs within
that group will be executed.
49/56`
Finally, the SchedulerFactory is used to get a Scheduler instance, which can
be used to register jobs and triggers.
Let's illustrate this with a basic example : a simple job printing a welcome
message, and a trigger firing the job every ten seconds.
First, the Job, only printing a welcome message:

Listing 5.2. RanchJob (Plain)


public class RanchJob implements Job {
public void execute (JobExecutionContext ctx) throws
JobExecutionException {
System.out.println("[JOB] Welcome at JavaRanch");
}
}

Then the scheduler, registering a trigger and a job:

Listing 5.3. RanchSchedule


public class RanchSchedule {
public static void main (String[] args) {
try {
SchedulerFactory factory =
new org.quartz.impl.StdSchedulerFactory();

Scheduler scheduler = factory.getScheduler();


scheduler.start();

JobDetail jobDetail = new JobDetail("ranchJob", null,


RanchJob.class);
// Fires every 10 seconds
Trigger ranchTrigger =
TriggerUtils.makeSecondlyTrigger(10);
ranchTrigger.setName("ranchTrigger");

scheduler.scheduleJob(jobDetail, ranchTrigger);
} catch (SchedulerException ex) {
ex.printStackTrace();
}
}
}

After executing RanchSchedule, [JOB] Welcome at JavaRanch is being printed


out every 10 seconds.
There are some others interesting things like Priority, TriggerUtils, listeners,
but they won't be discussed here.
If you want to know more about Quartz, there's a complete tutorial at Quartz's
homepage.

Spring and Quartz

50/56`
Spring's Quartz API resides in the org.springframework.scheduling.quartz
package. There's quite a few classes there, but we'll only see those needed to
fire up jobs.
The QuartzJobBean abstract class
The JobDetailBean class
The SimpleTriggerBean class
The CronTriggerBean class
The SchedulerFactoryBean class
The MethodInvokingJobDetailFactoryBean class
The wrapping of Quartz API is obvious. QuartzJobBean implements Job,
JobDetailBean extends JobDetail. No need to say which class
SimpleTriggerBean and CronTriggerBean extend.

MethodInvokingJobDetailFactoryBean is a nifty class to call methods in any


objects, instead of Quartz jobs. We'll see that last, but first let's make our
previous RanchJob running. (Note that we won't use groups for our jobs and
triggers)

Declaring Jobs
The JobDetailBean is used to declare jobs. We set the name of the job class,
and if needed, some data the job may use. The job class extends
QuartzJobBean. Here is the declaration:

51/56`
Listing 5.4. ranchJob Bean Declaration
<bean name="ranchJob"
class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="examples.spring.quartz.RanchJob"
/>
<property name="jobDataAsMap">
<map>
<entry key="message" value="Welcome at JavaRanch" />
</map>
</property>
</bean>

And the job class :

Listing 5.5. RanchJob


public class RanchJob extends QuartzJobBean {
@Override
protected void executeInternal (JobExecutionContext ctx)
throws JobExecutionException {
String message = (String)
ctx.getJobDetail().getJobDataMap().get("message");
System.out.println("[JOB] " + message);
}
}

Note how we retrieve the message from the context. This message was set in
the bean declaration, using the jobDataAsMap property. Spring actually calls
setter methods for each object set in this map. Here is the Spring way to use
the message in the job class :

Listing 5.6. RanchJob (Alternative)


public class RanchJob extends QuartzJobBean {
private String message;

public void setMessage (String message) {


this.message = message;
}

@Override
protected void executeInternal (JobExecutionContext ctx) throws
JobExecutionException {
System.out.println("[JOB] " + message);
}
}

Declaring Triggers
Declaring triggers is as simple as declaring a job. We'll only use a
SimpleTriggerBean, which will start immediately, and repeat every ten
seconds. You can refer to the CronTriggerBean API to check how to set a
cronExpression for your trigger.

52/56`
Listing 5.7. ranchTrigger Bean Declaration
<bean id="ranchTrigger"
class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail" ref="ranchJob" />
<property name="startDelay" value="0" />
<property name="repeatInterval" value="10000" />
</bean>

Declaring the Scheduler


Now that we have a job associated to a trigger, we need to register the
trigger. We declare Spring's SchedulerFactoryBean the following way :

Listing 5.8. Scheduler Bean Declaration


<bean
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="ranchTrigger" />
</list>
</property>
</bean>

Everything has been set up, all we need now is to load the context. The
scheduler will be started automatically on initialization.

Listing 5.9. RanchQuartz Declaration


public class RanchQuartz {
public static void main (String[] args) throws SchedulerException
{
ApplicationContext ctx = new
ClassPathXmlApplicationContext("config/schedule.xml");
}
}

Executing RanchQuartz will start the scheduler automatically. As expected,


The RanchJob will be fired immediately, and repeated every 10 seconds.

Using the MethodInvokingJobDetailFactoryBean

We've seen so far how to fire Quartz jobs, but what if you want to call your
own method of your own bean? With Spring, you are not tied to Quartz job
instances, you can also use your own pojos to act as jobs. For example, you
may wish to use the CronTrigger's advanced settings to fire up your own task.

Declaring the good old bean

Nothing special here. Just a good old bean, declared the good old way.

53/56`
Listing 5.10. A Plain Bean
<bean name="welcomeBean" class="examples.spring.quartz.RanchBean">
<property name="message" value="Welcome at JavaRanch" />
</bean>

And the implementation:

Listing 5.11. RanchBean


public class RanchBean {
private String message;

public void setMessage (String message) {


this.message = message;
}

public void welcome() {


System.out.println("[JOBBEAN] " + message);
}
}

Declaring the MethodInvokingJobDetailFactoryBean

When declaring the MethodInvokingJobDetailFactoryBean, we need to tell


Spring which method of which bean to call. Let's also modify our trigger to use
this new bean:

Listing 5.12. methodInvokingJob Bean Declaration


<bean id="methodInvokingJob"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetail
FactoryBean">
<property name="targetObject" ref="welcomeBean" />
<property name="targetMethod" value="welcome" />
</bean>

<bean id="ranchTrigger"
class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail" ref="methodInvokingJob" />
<property name="startDelay" value="0" />
<property name="repeatInterval" value="10000" />
</bean>

Voil! Executing the RanchQuartz application again will produce the same
result, with "[JOBBEAN]" being printed out instead of "[JOB]".

A word of caution
A trigger can fire only one job, but a job may be fired by many triggers. This
can bring a concurrency issue. In Quartz, if you don't want the same job to be
executed simultaneously, you can make it implement StatefulJob instead of
Job. In Spring, if you are using the MethodInvokingJobDetailFactoryBean, you
can set its "concurrent" property to false.

54/56`
Summary

Using Quartz with Spring instead as a standalone application offers the


following benefits :

Keeping all scheduling settings in one place. It makes scheduling


easier to maintain. It looks a bit like having one "cron" file for
scheduling tasks.
Coding only jobs. The scheduler, triggers and job details can be
configured in the context file.
Using plain old java objects for jobs, instead of Quartz jobs.

As stated at the beginning of this module Spring also supports JDK's Timer
objects. If you want to use a simple timer for a simple task as above, you may
consider using a TimerTask and Spring's ScheduledTimerTask and
TimerFactoryBean instead. If you decide to use Quartz in Spring, there are
many more properties that can be set for the scheduler, jobs and triggers.
Refer to Spring's API to discover them all.

55/56`
Finally

You should now have a pretty good idea of what Spring brings to the table.
Spring aims to make J2EE development easier, and central to this is its
inversion of control. This enables you to develop enterprise applications using
simple Java objects that collaborate with each other through interfaces. These
beans will be wired together at runtime by the Spring container. It lets you
maintain loosely coupled code with minimal cost.

On top of Springs inversion control, Springs container also offers AOP. This
allows you place code that would otherwise be scattered throughout you
application in one placean aspect. When your beans are wired together,
these aspects can be woven in at runtime, giving these beans new behavior.

Staying true to aiding enterprise development, Spring offers integration to


several persistence technologies. Whether you persist data using JDBC,
Hibernate, or JDO, Springs DAO frameworks ease your development by
providing a consistent model for error handling and resource management for
each of these persistence frameworks.

There are many topics that are not covered in this introduction, such as:

Resources
PropertyEditors, data binding, validation and the BeanWrapper
Transaction Management
Web MVC Framework
Remoting (exposing Spring services outside container)
Other Integration Subject, etc

But by this time you should be able to catch those topics up yourself, by
reading Spring Reference and lot of articles on the net.

Good luck and happy coding!

-)|(-

56/56`

You might also like